<?php

declare(strict_types=1);

use App\Filament\Pages\BaselineCompareLanding;
use App\Filament\Pages\BaselineCompareMatrix;
use App\Filament\Pages\Monitoring\AuditLog;
use App\Filament\Pages\Monitoring\EvidenceOverview;
use App\Filament\Pages\Monitoring\FindingExceptionsQueue;
use App\Filament\Pages\Monitoring\Operations;
use App\Models\AuditLog as AuditLogModel;
use App\Models\FindingException;

function monitoringPageStateFieldSummary(array $contract): array
{
    return collect($contract['stateFields'])
        ->mapWithKeys(static fn (array $field): array => [
            (string) $field['stateKey'] => [
                'stateClass' => $field['stateClass'],
                'queryRole' => $field['queryRole'],
                'shareable' => $field['shareable'],
                'restorableOnRefresh' => $field['restorableOnRefresh'],
            ],
        ])
        ->all();
}

it('declares the bounded page-state contract for each monitoring surface', function (string $pageClass, array $expected): void {
    $contract = $pageClass::monitoringPageStateContract();

    expect($contract['surfaceKey'])->toBe($expected['surfaceKey'])
        ->and($contract['surfaceType'])->toBe($expected['surfaceType'])
        ->and($contract['shareableStateKeys'])->toBe($expected['shareableStateKeys'])
        ->and($contract['localOnlyStateKeys'])->toBe($expected['localOnlyStateKeys'])
        ->and($contract['inspectContract'])->toMatchArray($expected['inspectContract'])
        ->and(monitoringPageStateFieldSummary($contract))->toEqual($expected['stateFields']);
})->with([
    'operations' => [
        Operations::class,
        [
            'surfaceKey' => 'operations',
            'surfaceType' => 'simple_monitoring',
            'shareableStateKeys' => ['environment_id', 'problemClass', 'activeTab'],
            'localOnlyStateKeys' => [],
            'inspectContract' => [
                'primaryModel' => 'none',
                'selectedStateKey' => null,
                'presentation' => 'none',
                'shareable' => false,
            ],
            'stateFields' => [
                'environment_id' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'problemClass' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'scoped_deeplink', 'shareable' => true, 'restorableOnRefresh' => true],
                'activeTab' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'tableFilters' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
            ],
        ],
    ],
    'audit log' => [
        AuditLog::class,
        [
            'surfaceKey' => 'audit_log',
            'surfaceType' => 'selected_record_monitoring',
            'shareableStateKeys' => ['event', 'supportAccess'],
            'localOnlyStateKeys' => [],
            'inspectContract' => [
                'primaryModel' => AuditLogModel::class,
                'selectedStateKey' => 'selectedAuditLogId',
                'presentation' => 'inline_detail',
                'shareable' => true,
            ],
            'stateFields' => [
                'event' => ['stateClass' => 'inspect', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'supportAccess' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'managed_environment_id' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => false, 'restorableOnRefresh' => true],
                'tableSearch' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
            ],
        ],
    ],
    'finding exceptions queue' => [
        FindingExceptionsQueue::class,
        [
            'surfaceKey' => 'finding_exceptions_queue',
            'surfaceType' => 'selected_record_monitoring',
            'shareableStateKeys' => ['environment_id', 'exception'],
            'localOnlyStateKeys' => [],
            'inspectContract' => [
                'primaryModel' => FindingException::class,
                'selectedStateKey' => 'selectedFindingExceptionId',
                'presentation' => 'summary_plus_related_actions',
                'shareable' => true,
            ],
            'stateFields' => [
                'exception' => ['stateClass' => 'inspect', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'environment_id' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'tableFilters' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
                'tableSearch' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
            ],
        ],
    ],
    'evidence overview' => [
        EvidenceOverview::class,
        [
            'surfaceKey' => 'evidence_overview',
            'surfaceType' => 'simple_monitoring',
            'shareableStateKeys' => ['environment_id', 'search'],
            'localOnlyStateKeys' => [],
            'inspectContract' => [
                'primaryModel' => 'none',
                'selectedStateKey' => null,
                'presentation' => 'navigate_to_canonical_detail',
                'shareable' => false,
            ],
            'stateFields' => [
                'environment_id' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'search' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'tableFilters' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
                'tableSort' => ['stateClass' => 'shareable_restorable', 'queryRole' => 'unsupported', 'shareable' => false, 'restorableOnRefresh' => true],
            ],
        ],
    ],
    'baseline compare landing' => [
        BaselineCompareLanding::class,
        [
            'surfaceKey' => 'baseline_compare_landing',
            'surfaceType' => 'launch_context_support',
            'shareableStateKeys' => ['baseline_profile_id', 'subject_key', 'nav'],
            'localOnlyStateKeys' => [],
            'inspectContract' => [
                'primaryModel' => 'none',
                'selectedStateKey' => null,
                'presentation' => 'none',
                'shareable' => true,
            ],
            'stateFields' => [
                'baseline_profile_id' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'scoped_deeplink', 'shareable' => true, 'restorableOnRefresh' => true],
                'subject_key' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'scoped_deeplink', 'shareable' => true, 'restorableOnRefresh' => true],
                'nav' => ['stateClass' => 'contextual_prefilter', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
            ],
        ],
    ],
    'baseline compare matrix' => [
        BaselineCompareMatrix::class,
        [
            'surfaceKey' => 'baseline_compare_matrix',
            'surfaceType' => 'draft_apply_analysis',
            'shareableStateKeys' => ['mode', 'policy_type', 'state', 'severity', 'tenant_sort', 'subject_sort', 'subject_key'],
            'localOnlyStateKeys' => [
                'draftSelectedPolicyTypes',
                'draftSelectedStates',
                'draftSelectedSeverities',
                'draftTenantSort',
                'draftSubjectSort',
            ],
            'inspectContract' => [
                'primaryModel' => 'baseline_subject',
                'selectedStateKey' => 'focusedSubjectKey',
                'presentation' => 'focused_matrix',
                'shareable' => true,
            ],
            'stateFields' => [
                'mode' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'policy_type' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'state' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'severity' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'tenant_sort' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'subject_sort' => ['stateClass' => 'active', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
                'subject_key' => ['stateClass' => 'inspect', 'queryRole' => 'durable_restorable', 'shareable' => true, 'restorableOnRefresh' => true],
            ],
        ],
    ],
]);

it('keeps the selected-record monitoring surfaces on a single inspect identifier', function (): void {
    $contracts = [
        AuditLog::monitoringPageStateContract(),
        FindingExceptionsQueue::monitoringPageStateContract(),
    ];

    expect(collect($contracts)->pluck('inspectContract.selectedStateKey')->all())
        ->toEqual(['selectedAuditLogId', 'selectedFindingExceptionId'])
        ->and(collect($contracts)->pluck('inspectContract.shareable')->unique()->all())
        ->toEqual([true]);
});

it('keeps compare matrix draft state local while applied filters stay query-driven', function (): void {
    $contract = BaselineCompareMatrix::monitoringPageStateContract();

    expect($contract['surfaceType'])->toBe('draft_apply_analysis')
        ->and($contract['localOnlyStateKeys'])->toEqual([
            'draftSelectedPolicyTypes',
            'draftSelectedStates',
            'draftSelectedSeverities',
            'draftTenantSort',
            'draftSubjectSort',
        ])
        ->and(collect($contract['shareableStateKeys'])->contains('subject_key'))->toBeTrue()
        ->and($contract['inspectContract']['presentation'])->toBe('focused_matrix');
});
