<?php

namespace MintyPHP\Tests\Module\Helpdesk\Service;

use MintyPHP\Module\Helpdesk\Service\RiskRadarService;
use PHPUnit\Framework\TestCase;

class RiskRadarServiceTest extends TestCase
{
    private static function ticket(
        string $no,
        string $customerNo,
        string $customerName,
        int $createdHoursAgo,
        bool $closed = false,
        string $escalationCode = '',
        int $resolutionHours = 0
    ): array {
        $now = time();
        $createdTs = $now - ($createdHoursAgo * 3600);
        $activityTs = $closed ? $createdTs + ($resolutionHours * 3600) : $createdTs;

        return [
            'No' => $no,
            'Customer_No' => $customerNo,
            'Cust_Name' => $customerName,
            'Escalation_Code' => $escalationCode,
            'Created_On' => gmdate('Y-m-d\TH:i:s\Z', $createdTs),
            'Last_Activity_Date' => gmdate('Y-m-d\TH:i:s\Z', $activityTs),
            'Process_Stage' => $closed ? 40 : 10,
            'Ticket_State' => $closed ? 'Geschlossen' : 'Offen',
            'Support_User_Name' => 'NKS',
            'Category_1_Code' => 'FEHLER',
            'Process_Code' => 'NORMAL',
        ];
    }

    public function testEmptyTicketsReturnsEmptyResult(): void
    {
        $result = RiskRadarService::buildRiskRadar([], [], 90);

        $this->assertSame(0, $result['summary']['total']);
        $this->assertSame([], $result['customers']);
    }

    public function testSkipsTicketsWithoutCustomerNo(): void
    {
        $tickets = [
            self::ticket('T1', '', 'No Customer', 10),
            self::ticket('T2', '10610', 'Valid Customer', 10),
        ];

        $result = RiskRadarService::buildRiskRadar($tickets, [], 90);

        $this->assertSame(1, $result['summary']['total']);
        $this->assertSame('10610', $result['customers'][0]['customer_no']);
    }

    public function testAggregatesPerCustomerNo(): void
    {
        $tickets = [
            self::ticket('T1', '10610', 'Kunde A', 10),
            self::ticket('T2', '10610', 'Kunde A', 20),
            self::ticket('T3', '10620', 'Kunde B', 5),
        ];

        $result = RiskRadarService::buildRiskRadar($tickets, [], 90);

        $this->assertSame(2, $result['summary']['total']);
        $customerNos = array_column($result['customers'], 'customer_no');
        $this->assertContains('10610', $customerNos);
        $this->assertContains('10620', $customerNos);

        $kundeA = $result['customers'][array_search('10610', $customerNos)];
        $this->assertSame(2, $kundeA['kpis']['open']);
    }

    public function testHighRiskLevel(): void
    {
        // Many open + critical tickets → high score
        $tickets = [];
        for ($i = 0; $i < 10; $i++) {
            $tickets[] = self::ticket('T' . $i, '10610', 'Stressed', 100); // all >48h → critical
        }

        $result = RiskRadarService::buildRiskRadar($tickets, [], 90);

        $this->assertSame('high', $result['customers'][0]['risk_level']);
        $this->assertGreaterThanOrEqual(55, $result['customers'][0]['risk_score']);
    }

    public function testLowRiskLevel(): void
    {
        // One recently closed ticket, one just opened
        $tickets = [
            self::ticket('T1', '10610', 'Calm', 2),
            self::ticket('T2', '10610', 'Calm', 10, true, '', 2),
        ];

        $result = RiskRadarService::buildRiskRadar($tickets, [], 90);

        $this->assertSame('low', $result['customers'][0]['risk_level']);
        $this->assertLessThan(25, $result['customers'][0]['risk_score']);
    }

    public function testSlaOverdueDetection(): void
    {
        $escalationDefs = [
            ['Code' => 'MAX', 'Target_Time' => 'PT2H', 'No_of_Escalation_Level' => 1],
        ];

        // Ticket created 10h ago with MAX escalation, target 2h → overdue
        $tickets = [
            self::ticket('T1', '10610', 'SLA Breach', 10, false, 'MAX'),
        ];

        $result = RiskRadarService::buildRiskRadar($tickets, $escalationDefs, 90);

        $this->assertSame(1, $result['customers'][0]['kpis']['sla_overdue']);
    }

    public function testSlaNotOverdueWhenWithinTarget(): void
    {
        $escalationDefs = [
            ['Code' => 'NORMAL', 'Target_Time' => 'P30D', 'No_of_Escalation_Level' => 1],
        ];

        $tickets = [
            self::ticket('T1', '10610', 'Within SLA', 10, false, 'NORMAL'),
        ];

        $result = RiskRadarService::buildRiskRadar($tickets, $escalationDefs, 90);

        $this->assertSame(0, $result['customers'][0]['kpis']['sla_overdue']);
    }

    public function testFourDimensionsInOutput(): void
    {
        $tickets = [
            self::ticket('T1', '10610', 'Any', 10),
        ];

        $result = RiskRadarService::buildRiskRadar($tickets, [], 90);

        $dimIds = array_column($result['customers'][0]['dimensions'], 'id');
        $this->assertSame(['open_pressure', 'trend', 'sla_overdue', 'inactivity'], $dimIds);
    }

    public function testTruncatedFlagPassthrough(): void
    {
        $tickets = [self::ticket('T1', '10610', 'Any', 5)];

        $result = RiskRadarService::buildRiskRadar($tickets, [], 90, true);

        $this->assertTrue($result['meta']['truncated']);
        $this->assertSame('medium', $result['meta']['confidence']);
    }

    public function testSortsByScoreDescending(): void
    {
        $tickets = [
            self::ticket('T1', '10610', 'Low Risk', 2),
            self::ticket('T2', '10620', 'High Risk', 100),
            self::ticket('T3', '10620', 'High Risk', 100),
            self::ticket('T4', '10620', 'High Risk', 100),
        ];

        $result = RiskRadarService::buildRiskRadar($tickets, [], 90);

        $this->assertSame('10620', $result['customers'][0]['customer_no']);
        $this->assertSame('10610', $result['customers'][1]['customer_no']);
    }

    public function testTopDriversSortedByWeightedPoints(): void
    {
        $tickets = [];
        for ($i = 0; $i < 8; $i++) {
            $tickets[] = self::ticket('T' . $i, '10610', 'Heavy', 200);
        }

        $result = RiskRadarService::buildRiskRadar($tickets, [], 90);

        $drivers = $result['customers'][0]['drivers'];
        $this->assertCount(3, $drivers);
        $this->assertGreaterThanOrEqual($drivers[1]['weighted_points'], $drivers[0]['weighted_points']);
    }

    public function testExcludesInactiveCustomers(): void
    {
        // Ticket created and closed outside the period window
        $tickets = [
            self::ticket('T1', '10610', 'Old', 3000, true, '', 10),
        ];

        $result = RiskRadarService::buildRiskRadar($tickets, [], 30);

        // Customer had no activity in the 30-day window and no open tickets
        $this->assertSame(0, $result['summary']['total']);
    }
}
