<?php

app_require('classes/department_outside_hours_statistics_service.php');

use classes\department_outside_hours_statistics_service;

function outside_hours_weekday_hours(int $department_id, array $overrides = []): array
{
    return array_merge([
        'department' => $department_id,
        'monday_start' => '08:00:00',
        'monday_end' => '17:00:00',
        'tuesday_start' => '08:00:00',
        'tuesday_end' => '17:00:00',
        'wednesday_start' => '08:00:00',
        'wednesday_end' => '17:00:00',
        'thursday_start' => '08:00:00',
        'thursday_end' => '17:00:00',
        'friday_start' => '08:00:00',
        'friday_end' => '17:00:00',
        'saturday_start' => '08:00:00',
        'saturday_end' => '17:00:00',
        'sunday_start' => '08:00:00',
        'sunday_end' => '17:00:00',
    ], $overrides);
}

it('counts only outside-hours washes and flags missing opening hours without counting them as closed', function (): void {
    $service = new department_outside_hours_statistics_service();

    $summary = $service->summarizeCandidates(
        [
            [
                'source' => 'orders',
                'dedupe_key' => 'order:100',
                'department_id' => 1,
                'start_at' => '2026-03-23 06:45:00',
            ],
            [
                'source' => 'orders',
                'dedupe_key' => 'order:101',
                'department_id' => 1,
                'start_at' => '2026-03-23 10:15:00',
            ],
            [
                'source' => 'orders',
                'dedupe_key' => 'order:102',
                'department_id' => 2,
                'start_at' => '2026-03-23 05:30:00',
            ],
        ],
        [
            1 => outside_hours_weekday_hours(1),
            2 => outside_hours_weekday_hours(2, [
                'monday_start' => null,
                'monday_end' => null,
            ]),
        ],
        [1, 2],
        '2026-03-23',
        '2026-03-23'
    );

    expect($summary['total'])->toBe(1);
    expect($summary['by_source'])->toBe([
        'orders' => 1,
        'xlvask' => 0,
        'selfserve' => 0,
    ]);
    expect($summary['has_missing_opening_hours'])->toBeTrue();
    expect($summary['missing_department_ids'])->toBe([2]);
});

it('deduplicates linked washes with self-serve first, then xlvask, then orders', function (): void {
    $service = new department_outside_hours_statistics_service();

    $deduplicated = $service->deduplicateCandidates([
        [
            'source' => 'orders',
            'dedupe_key' => 'order:200',
            'department_id' => 1,
            'start_at' => '2026-03-23 06:00:00',
        ],
        [
            'source' => 'xlvask',
            'dedupe_key' => 'order:200',
            'department_id' => 1,
            'start_at' => '2026-03-23 06:05:00',
        ],
        [
            'source' => 'selfserve',
            'dedupe_key' => 'order:200',
            'department_id' => 1,
            'start_at' => '2026-03-23 06:10:00',
        ],
        [
            'source' => 'xlvask',
            'dedupe_key' => 'xlvask:wash-standalone',
            'department_id' => 1,
            'start_at' => '2026-03-23 23:00:00',
        ],
        [
            'source' => 'selfserve',
            'dedupe_key' => 'selfserve:501',
            'department_id' => 1,
            'start_at' => '2026-03-23 23:30:00',
        ],
    ]);

    expect($deduplicated)->toHaveCount(3);
    expect($deduplicated[0]['source'])->toBe('selfserve');
    expect($deduplicated[0]['dedupe_key'])->toBe('order:200');
    expect(array_column($deduplicated, 'source'))->toBe([
        'selfserve',
        'xlvask',
        'selfserve',
    ]);
});

it('builds daily trend points with per-day missing-hours diagnostics', function (): void {
    $service = new department_outside_hours_statistics_service();

    $trend = $service->buildTrendFromCandidates(
        [
            [
                'source' => 'orders',
                'dedupe_key' => 'order:301',
                'department_id' => 1,
                'start_at' => '2026-03-23 06:00:00',
            ],
            [
                'source' => 'orders',
                'dedupe_key' => 'order:302',
                'department_id' => 2,
                'start_at' => '2026-03-23 05:00:00',
            ],
            [
                'source' => 'selfserve',
                'dedupe_key' => 'selfserve:701',
                'department_id' => 2,
                'start_at' => '2026-03-24 05:15:00',
            ],
        ],
        [
            1 => outside_hours_weekday_hours(1),
            2 => outside_hours_weekday_hours(2, [
                'monday_start' => null,
                'monday_end' => null,
            ]),
        ],
        [1, 2],
        '2026-03-23',
        '2026-03-24'
    );

    expect($trend['has_missing_opening_hours'])->toBeTrue();
    expect($trend['missing_department_ids'])->toBe([2]);
    expect($trend['points'])->toBe([
        [
            'date' => '2026-03-23',
            'total' => 1,
            'by_source' => [
                'orders' => 1,
                'xlvask' => 0,
                'selfserve' => 0,
            ],
            'has_missing_opening_hours' => true,
            'missing_department_ids' => [2],
        ],
        [
            'date' => '2026-03-24',
            'total' => 1,
            'by_source' => [
                'orders' => 0,
                'xlvask' => 0,
                'selfserve' => 1,
            ],
            'has_missing_opening_hours' => false,
            'missing_department_ids' => [],
        ],
    ]);
});
