<?php

namespace MintyPHP\Tests\Module\Helpdesk\Service;

use MintyPHP\Module\Helpdesk\Repository\HandoverRepository;
use MintyPHP\Module\Helpdesk\Service\BcODataGateway;
use MintyPHP\Module\Helpdesk\Service\DomainDetailService;
use MintyPHP\Module\Helpdesk\Service\EffectiveHelpdeskSettingsService;
use PHPUnit\Framework\TestCase;

class DomainDetailServiceTest extends TestCase
{
    private const TENANT_ID = 1;

    private function createService(
        ?BcODataGateway $gateway = null,
        ?EffectiveHelpdeskSettingsService $settings = null,
        ?HandoverRepository $repository = null,
    ): DomainDetailService {
        $gateway = $gateway ?? $this->createMock(BcODataGateway::class);
        $settings = $settings ?? $this->createConfiguredSettings(true);
        $repository = $repository ?? $this->createMock(HandoverRepository::class);

        return new DomainDetailService($gateway, $settings, $repository);
    }

    private function createConfiguredSettings(bool $configured): EffectiveHelpdeskSettingsService
    {
        $mock = $this->createMock(EffectiveHelpdeskSettingsService::class);
        $mock->method('isConfigured')->willReturn($configured);

        return $mock;
    }

    // ── loadDomain tests ─────────────────────────────────────────

    public function testLoadDomainHappyPath(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->method('getDomain')->willReturn([
            'No' => 'DNS00001',
            'Customer_No' => 'D10001',
            'Customer_Name' => 'Acme Corp',
            'URL' => 'example.com',
            'State' => 'Aktiv',
            'Administration' => 'Intern',
        ]);

        $service = $this->createService($gateway);
        $result = $service->loadDomain('DNS00001');

        $this->assertSame('success', $result['status']);
        $this->assertSame('DNS00001', $result['domain']['No']);
        $this->assertSame('example.com', $result['domain']['URL']);
    }

    public function testLoadDomainNotFound(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->method('getDomain')->willReturn(null);

        $service = $this->createService($gateway);
        $result = $service->loadDomain('INVALID');

        $this->assertSame('not_found', $result['status']);
    }

    public function testLoadDomainEmptyNo(): void
    {
        $service = $this->createService();
        $result = $service->loadDomain('');

        $this->assertSame('not_found', $result['status']);
    }

    public function testLoadDomainNotConfigured(): void
    {
        $service = $this->createService(settings: $this->createConfiguredSettings(false));
        $result = $service->loadDomain('DNS00001');

        $this->assertSame('not_configured', $result['status']);
    }

    public function testLoadDomainBcError(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->method('getDomain')->willThrowException(new \RuntimeException('Connection failed'));

        $service = $this->createService($gateway);
        $result = $service->loadDomain('DNS00001');

        $this->assertSame('error', $result['status']);
        $this->assertSame('BC connection failed', $result['error']);
    }

    // ── loadDomainDetails tests ──────────────────────────────────

    public function testLoadDomainDetailsHappyPath(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->method('getCustomer')->willReturn([
            'No' => 'D10001',
            'Name' => 'Acme Corp',
            'Address' => 'Main St 1',
        ]);
        $gateway->method('listDomainContractLines')->willReturn([
            ['No' => 'DNS00001', 'Header_No' => 'V1000', 'PI_Header_Type' => 'WEBSITE', 'PI_Header_Description' => 'Website Contract', 'PI_Header_State' => 'Aktiv', 'Line_State' => 'Aktiv'],
            ['No' => 'DNS00002', 'Header_No' => 'V2000', 'PI_Header_Type' => 'SW&H', 'PI_Header_Description' => 'Other', 'PI_Header_State' => 'Aktiv', 'Line_State' => 'Aktiv'],
        ]);
        $gateway->method('getDomainsForCustomer')->willReturn([
            ['No' => 'DNS00001', 'URL' => 'example.com', 'State' => 'Aktiv'],
            ['No' => 'DNS00002', 'URL' => 'other.com', 'State' => 'Aktiv'],
        ]);

        $repo = $this->createMock(HandoverRepository::class);
        $repo->method('findByDomainNo')->willReturn([
            ['id' => 1, 'product_code' => 'PROD-A', 'product_name' => 'Product A', 'product_bc_description' => '', 'status' => 'draft', 'created_by_name' => 'John', 'created_at' => '2026-01-01 10:00:00'],
            ['id' => 2, 'product_code' => 'PROD-A', 'product_name' => 'Product A', 'product_bc_description' => '', 'status' => 'completed', 'created_by_name' => 'Jane', 'created_at' => '2026-02-15 14:00:00'],
        ]);

        $service = $this->createService($gateway, repository: $repo);
        $result = $service->loadDomainDetails('DNS00001', 'D10001', self::TENANT_ID);

        $this->assertTrue($result['ok']);
        $this->assertSame('Acme Corp', $result['customer']['Name']);
        $this->assertSame('WEBSITE', $result['contract']['contract_type']);
        $this->assertSame('V1000', $result['contract']['contract_no']);
        $this->assertCount(2, $result['handovers']);
        $this->assertSame(2, $result['handover_stats']['total']);
        $this->assertSame(1, $result['handover_stats']['draft']);
        $this->assertSame(1, $result['handover_stats']['completed']);
        $this->assertCount(1, $result['related_domains']);
        $this->assertSame('DNS00002', $result['related_domains'][0]['No']);
    }

    public function testLoadDomainDetailsNoContract(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->method('getCustomer')->willReturn(['No' => 'D10001', 'Name' => 'Acme']);
        $gateway->method('listDomainContractLines')->willReturn([]);
        $gateway->method('getDomainsForCustomer')->willReturn([]);

        $repo = $this->createMock(HandoverRepository::class);
        $repo->method('findByDomainNo')->willReturn([]);

        $service = $this->createService($gateway, repository: $repo);
        $result = $service->loadDomainDetails('DNS00001', 'D10001', self::TENANT_ID);

        $this->assertTrue($result['ok']);
        $this->assertNull($result['contract']);
        $this->assertSame(0, $result['handover_stats']['total']);
        $this->assertEmpty($result['related_domains']);
    }

    public function testLoadDomainDetailsEmptyDomainNo(): void
    {
        $service = $this->createService();
        $result = $service->loadDomainDetails('', 'D10001', self::TENANT_ID);

        $this->assertFalse($result['ok']);
        $this->assertSame('Missing domain number', $result['error']);
    }

    public function testLoadDomainDetailsCustomerFetchFails(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->method('getCustomer')->willThrowException(new \RuntimeException('BC error'));
        $gateway->method('listDomainContractLines')->willReturn([]);
        $gateway->method('getDomainsForCustomer')->willReturn([]);

        $repo = $this->createMock(HandoverRepository::class);
        $repo->method('findByDomainNo')->willReturn([]);

        $service = $this->createService($gateway, repository: $repo);
        $result = $service->loadDomainDetails('DNS00001', 'D10001', self::TENANT_ID);

        $this->assertTrue($result['ok']);
        $this->assertNull($result['customer']);
    }

    public function testLoadDomainDetailsHandoverStatAggregation(): void
    {
        $gateway = $this->createMock(BcODataGateway::class);
        $gateway->method('getCustomer')->willReturn(null);
        $gateway->method('listDomainContractLines')->willReturn([]);
        $gateway->method('getDomainsForCustomer')->willReturn([]);

        $repo = $this->createMock(HandoverRepository::class);
        $repo->method('findByDomainNo')->willReturn([
            ['id' => 1, 'product_code' => 'P', 'product_name' => '', 'product_bc_description' => '', 'status' => 'draft', 'created_by_name' => '', 'created_at' => ''],
            ['id' => 2, 'product_code' => 'P', 'product_name' => '', 'product_bc_description' => '', 'status' => 'in_progress', 'created_by_name' => '', 'created_at' => ''],
            ['id' => 3, 'product_code' => 'P', 'product_name' => '', 'product_bc_description' => '', 'status' => 'in_progress', 'created_by_name' => '', 'created_at' => ''],
            ['id' => 4, 'product_code' => 'P', 'product_name' => '', 'product_bc_description' => '', 'status' => 'archived', 'created_by_name' => '', 'created_at' => ''],
        ]);

        $service = $this->createService($gateway, repository: $repo);
        $result = $service->loadDomainDetails('DNS00001', '', self::TENANT_ID);

        $this->assertSame(4, $result['handover_stats']['total']);
        $this->assertSame(1, $result['handover_stats']['draft']);
        $this->assertSame(2, $result['handover_stats']['in_progress']);
        $this->assertSame(0, $result['handover_stats']['completed']);
        $this->assertSame(1, $result['handover_stats']['archived']);
    }
}
