<?php

app_require('classes/bird.php');
app_require('classes/object_property.php');
app_require('classes/slack.php');
app_require('objects/department_gates_o.php');

use classes\bird;
use classes\object_property;
use classes\slack;
use objects\department_gates_o;

final class DepartmentGatesPhoneCallBirdFake extends bird
{
    public array $gateCalls = [];
    public ?\Throwable $exceptionToThrow = null;

    public function __construct()
    {
        // Intentionally skip parent constructor for unit isolation.
    }

    public function callGatePreferringFlashCall(int $countryCode, int $phone, int $timeout): void
    {
        if ($this->exceptionToThrow !== null) {
            throw $this->exceptionToThrow;
        }

        $this->gateCalls[] = [
            'countryCode' => $countryCode,
            'phone' => $phone,
            'timeout' => $timeout,
        ];
    }
}

final class DepartmentGatesPhoneCallSlackFake extends slack
{
    public array $messages = [];

    public function send_message(string $string, string $module = null): void
    {
        $this->messages[] = [
            'message' => $string,
            'module' => $module,
        ];
    }
}

final class DepartmentGatesPhoneCallOpenHarness extends department_gates_o
{
    public function __construct(
        array $config,
        private readonly DepartmentGatesPhoneCallBirdFake $birdClient,
        private readonly DepartmentGatesPhoneCallSlackFake $slackClient,
    ) {
        $this->id = 999;
        $configProperty = new object_property('department_gates', -1, 'config', 'json');
        $configProperty->set($config);
        $this->config = $configProperty;
    }

    public function requireSelected(): void
    {
        // Test harness objects are always considered selected.
    }

    protected function resolveBirdClient(): bird
    {
        return $this->birdClient;
    }

    protected function resolveSlackClient(): slack
    {
        return $this->slackClient;
    }
}

it('forwards phone number and call duration threshold to the Bird gate helper', function (): void {
    $birdClient = new DepartmentGatesPhoneCallBirdFake();
    $slackClient = new DepartmentGatesPhoneCallSlackFake();
    $gate = new DepartmentGatesPhoneCallOpenHarness([
        'type' => 'PHONE_CALL',
        'phone_number' => '+45 30 87 84 10',
        'call_duration_threshold' => 17,
    ], $birdClient, $slackClient);

    $gate->openGate();

    expect($birdClient->gateCalls)->toBe([
        [
            'countryCode' => 45,
            'phone' => 30878410,
            'timeout' => 17,
        ],
    ]);
    expect($slackClient->messages)->toBe([]);
});

it('wraps Bird helper failures and reports them to Slack', function (): void {
    $birdClient = new DepartmentGatesPhoneCallBirdFake();
    $birdClient->exceptionToThrow = new \RuntimeException('provider timeout');
    $slackClient = new DepartmentGatesPhoneCallSlackFake();
    $gate = new DepartmentGatesPhoneCallOpenHarness([
        'type' => 'PHONE_CALL',
        'phone_number' => '+45 30 87 84 10',
        'call_duration_threshold' => 12,
    ], $birdClient, $slackClient);

    expect(fn() => $gate->openGate())
        ->toThrow(\Exception::class, 'Failed to open gate relay via phone call');

    expect($slackClient->messages)->toHaveCount(1);
    expect($slackClient->messages[0]['message'])->toContain('provider timeout');
});
