<?php

declare(strict_types=1);

use App\Exceptions\Supplier\SupplierAuthException;
use App\Services\Supplier\PlaywrightBridge;
use App\Services\Supplier\ProcessFactory;
use Tests\TestCase;
use Tests\Unit\Supplier\Stubs\StubPlaywrightProcessHandle;

uses(TestCase::class);

test('PlaywrightBridge passes credentials via stdin not argv', function () {
    $stubHandle = new StubPlaywrightProcessHandle(
        successful: true,
        output: json_encode([
            'phpsessid' => 'abc123',
            'csrf' => 'xyz789',
            'refreshed_at' => '2026-05-11T10:00:00Z',
        ]),
    );

    $factoryMock = Mockery::mock(ProcessFactory::class);
    /** @var ProcessFactory $factoryMock */
    $factoryMock->shouldReceive('create')->andReturn($stubHandle);

    $bridge = new PlaywrightBridge($factoryMock);
    $result = $bridge->refreshSession(
        login: 'test_login',
        password: 'test_password',
        url: 'https://crm.bp-gr.ru'
    );

    // Credentials must come through stdin, not argv (avoid leak in ps output)
    $capturedInput = json_decode($stubHandle->capturedInput, true);
    expect($capturedInput)->toBeArray()
        ->and($capturedInput['login'])->toBe('test_login')
        ->and($capturedInput['password'])->toBe('test_password')
        ->and($capturedInput['url'])->toBe('https://crm.bp-gr.ru');

    expect($stubHandle->capturedTimeout)->toBe(75);

    expect($result)->toHaveKeys(['phpsessid', 'csrf', 'refreshed_at'])
        ->and($result['phpsessid'])->toBe('abc123')
        ->and($result['csrf'])->toBe('xyz789');
});

test('PlaywrightBridge throws SupplierAuthException on non-zero exit', function () {
    $stubHandle = new StubPlaywrightProcessHandle(
        successful: false,
        errorOutput: '{"error":"login rejected"}',
        exitCode: 1,
    );

    $factoryMock = Mockery::mock(ProcessFactory::class);
    $factoryMock->shouldReceive('create')->andReturn($stubHandle);

    $bridge = new PlaywrightBridge($factoryMock);

    expect(fn () => $bridge->refreshSession('bad', 'bad', 'https://crm.bp-gr.ru'))
        ->toThrow(SupplierAuthException::class);
});

test('PlaywrightBridge throws SupplierAuthException on invalid stdout JSON', function () {
    $stubHandle = new StubPlaywrightProcessHandle(
        successful: true,
        output: 'not valid json{',
    );

    $factoryMock = Mockery::mock(ProcessFactory::class);
    $factoryMock->shouldReceive('create')->andReturn($stubHandle);

    $bridge = new PlaywrightBridge($factoryMock);

    expect(fn () => $bridge->refreshSession('a', 'b', 'https://crm.bp-gr.ru'))
        ->toThrow(SupplierAuthException::class);
});

test('PlaywrightBridge throws SupplierAuthException on missing keys in stdout', function () {
    $stubHandle = new StubPlaywrightProcessHandle(
        successful: true,
        output: json_encode(['phpsessid' => 'a']),  // no csrf
    );

    $factoryMock = Mockery::mock(ProcessFactory::class);
    $factoryMock->shouldReceive('create')->andReturn($stubHandle);

    $bridge = new PlaywrightBridge($factoryMock);

    expect(fn () => $bridge->refreshSession('a', 'b', 'https://crm.bp-gr.ru'))
        ->toThrow(SupplierAuthException::class);
});
