<?php

declare(strict_types=1);

use App\Filament\Pages\InventoryCoverage;
use App\Models\InventoryItem;
use App\Models\OperationRun;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Models\WorkspaceMembership;
use App\Support\Badges\BadgeCatalog;
use App\Support\Badges\BadgeDomain;
use App\Support\Inventory\InventoryCoverage as InventoryCoveragePayload;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Livewire\Features\SupportTesting\Testable;
use Livewire\Livewire;

uses(RefreshDatabase::class);

function inventoryCoverageRecordKey(string $segment, string $type): string
{
    return "{$segment}:{$type}";
}

function inventoryCoverageComponent(User $user, ManagedEnvironment $tenant): Testable
{
    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    test()->actingAs($user);

    return Livewire::actingAs($user)->test(InventoryCoverage::class);
}

function seedTruthfulCoverageRun(ManagedEnvironment $tenant): OperationRun
{
    InventoryItem::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'display_name' => 'Conditional Access Prod',
        'policy_type' => 'conditionalAccessPolicy',
        'external_id' => 'ca-1',
        'platform' => 'windows',
    ]);

    InventoryItem::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'display_name' => 'Compliance Legacy',
        'policy_type' => 'deviceCompliancePolicy',
        'external_id' => 'dc-1',
        'platform' => 'windows',
    ]);

    return OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'type' => 'inventory_sync',
        'status' => 'completed',
        'outcome' => 'partially_succeeded',
        'context' => [
            'inventory' => [
                'coverage' => InventoryCoveragePayload::buildPayload([
                    'conditionalAccessPolicy' => [
                        'status' => InventoryCoveragePayload::StatusSucceeded,
                        'item_count' => 1,
                    ],
                    'deviceConfiguration' => [
                        'status' => InventoryCoveragePayload::StatusFailed,
                        'item_count' => 0,
                        'error_code' => 'graph_forbidden',
                    ],
                    'roleScopeTag' => [
                        'status' => InventoryCoveragePayload::StatusSkipped,
                        'item_count' => 0,
                    ],
                ], ['roleScopeTag']),
            ],
        ],
        'completed_at' => now(),
    ]);
}

it('renders truthful coverage states and deterministic follow-up order', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');
    seedTruthfulCoverageRun($tenant);

    $failedKey = inventoryCoverageRecordKey('policy', 'deviceConfiguration');
    $unknownKey = inventoryCoverageRecordKey('policy', 'deviceCompliancePolicy');
    $skippedKey = inventoryCoverageRecordKey('foundation', 'roleScopeTag');
    $succeededKey = inventoryCoverageRecordKey('policy', 'conditionalAccessPolicy');

    inventoryCoverageComponent($user, $tenant)
        ->assertOk()
        ->assertTableColumnExists('coverage_state')
        ->assertTableColumnExists('label')
        ->assertTableColumnExists('follow_up_guidance')
        ->assertTableColumnExists('observed_item_count')
        ->assertTableColumnExists('category')
        ->assertCanSeeTableRecords([$failedKey, $unknownKey, $skippedKey], inOrder: true)
        ->assertTableColumnFormattedStateSet(
            'coverage_state',
            BadgeCatalog::spec(BadgeDomain::InventoryCoverageState, 'failed')->label,
            $failedKey,
        )
        ->assertTableColumnFormattedStateSet(
            'coverage_state',
            BadgeCatalog::spec(BadgeDomain::InventoryCoverageState, 'unknown')->label,
            $unknownKey,
        )
        ->assertTableColumnFormattedStateSet(
            'coverage_state',
            BadgeCatalog::spec(BadgeDomain::InventoryCoverageState, 'skipped')->label,
            $skippedKey,
        )
        ->assertTableColumnFormattedStateSet(
            'coverage_state',
            BadgeCatalog::spec(BadgeDomain::InventoryCoverageState, 'succeeded')->label,
            $succeededKey,
        )
        ->assertTableColumnFormattedStateSet(
            'follow_up_guidance',
            'Review provider consent or permissions, then rerun inventory sync.',
            $failedKey,
        )
        ->assertTableColumnFormattedStateSet(
            'follow_up_guidance',
            'No current basis result exists for this type. Run inventory sync to confirm coverage.',
            $unknownKey,
        )
        ->assertTableColumnStateSet('observed_item_count', 1, $unknownKey)
        ->searchTable('Compliance')
        ->assertCanSeeTableRecords([$unknownKey])
        ->assertCanNotSeeTableRecords([$failedKey, $skippedKey, $succeededKey]);
});

it('filters truthful coverage rows by state, category, and restore metadata', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');
    seedTruthfulCoverageRun($tenant);

    $failedKey = inventoryCoverageRecordKey('policy', 'deviceConfiguration');
    $unknownKey = inventoryCoverageRecordKey('policy', 'deviceCompliancePolicy');
    $skippedKey = inventoryCoverageRecordKey('foundation', 'roleScopeTag');
    $succeededKey = inventoryCoverageRecordKey('policy', 'conditionalAccessPolicy');

    inventoryCoverageComponent($user, $tenant)
        ->assertTableFilterExists('coverage_state')
        ->assertTableFilterExists('category')
        ->assertTableFilterExists('restore')
        ->filterTable('coverage_state', 'failed')
        ->assertCanSeeTableRecords([$failedKey])
        ->assertCanNotSeeTableRecords([$unknownKey, $skippedKey, $succeededKey])
        ->removeTableFilters()
        ->filterTable('category', 'Foundations')
        ->assertCanSeeTableRecords([$skippedKey])
        ->assertCanNotSeeTableRecords([$failedKey, $unknownKey, $succeededKey])
        ->removeTableFilters()
        ->filterTable('restore', 'preview-only')
        ->assertCanSeeTableRecords([$succeededKey])
        ->assertCanNotSeeTableRecords([$failedKey, $skippedKey]);
});

it('shows a clear-filters empty state for the derived truth table', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');
    seedTruthfulCoverageRun($tenant);

    inventoryCoverageComponent($user, $tenant)
        ->assertTableEmptyStateActionsExistInOrder(['clear_filters'])
        ->searchTable('no-such-coverage-entry')
        ->assertCountTableRecords(0)
        ->assertSee('No coverage rows match this report')
        ->assertSee('Clear filters');
});

it('returns 404 for non-members on the inventory coverage page even when basis truth exists', function (): void {
    [$owner, $tenant] = createUserWithTenant(role: 'owner');
    seedTruthfulCoverageRun($tenant);

    $this->actingAs($owner);
    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    $outsider = User::factory()->create();
    WorkspaceMembership::factory()->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'user_id' => (int) $outsider->getKey(),
        'role' => 'owner',
    ]);
    createUserWithTenant(
        tenant: ManagedEnvironment::factory()->create(['workspace_id' => (int) $tenant->workspace_id]),
        user: $outsider,
        role: 'owner',
    );

    $this->actingAs($outsider);
    $tenant->makeCurrent();
    Filament::setTenant($tenant, true);

    $this->get(InventoryCoverage::getUrl(tenant: $tenant))
        ->assertNotFound();
});
