<?php

declare(strict_types=1);

use App\Filament\Pages\EnvironmentDashboard;
use App\Models\AuditLog;
use App\Models\SupportRequest;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Support\Audit\AuditActionId;
use App\Support\Workspaces\WorkspaceContext;
use Illuminate\Support\Facades\Http;
use Livewire\Livewire;

uses(\Illuminate\Foundation\Testing\RefreshDatabase::class);

function spec256ConfigureAuditSupportDesk(array $overrides = []): void
{
    config([
        'support_desk.target' => array_merge([
            'enabled' => true,
            'name' => 'Spec 256 Desk',
            'create_url' => 'https://desk.example.test/api/tickets',
            'api_token' => null,
            'ticket_url_template' => 'https://desk.example.test/tickets/{reference}',
            'timeout_seconds' => 5,
        ], $overrides),
    ]);
}

function spec256AuditTenantComponent(User $user, ManagedEnvironment $tenant): \Livewire\Features\SupportTesting\Testable
{
    test()->actingAs($user);
    session()->put(WorkspaceContext::SESSION_KEY, (int) $tenant->workspace_id);
    setAdminEnvironmentContext($tenant);

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

it('preserves support request created audit and records external ticket created audit', function (): void {
    spec256ConfigureAuditSupportDesk();

    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'owner');

    Http::fake([
        'desk.example.test/*' => Http::response([
            'ticket_reference' => 'PSA-AUDIT-CREATED',
            'raw_secret' => 'must-not-be-copied',
        ], 201),
    ]);

    spec256AuditTenantComponent($user, $tenant)
        ->mountAction('requestSupport')
        ->setActionData([
            'summary' => 'Audit external ticket created.',
            'external_handoff_mode' => SupportRequest::EXTERNAL_HANDOFF_MODE_CREATE_EXTERNAL_TICKET,
        ])
        ->callMountedAction()
        ->assertHasNoActionErrors();

    $supportRequest = SupportRequest::query()->sole();

    $createdAudit = AuditLog::query()
        ->where('action', AuditActionId::SupportRequestCreated->value)
        ->sole();

    $externalAudit = AuditLog::query()
        ->where('action', AuditActionId::SupportRequestExternalTicketCreated->value)
        ->sole();

    expect($createdAudit->resource_id)->toBe((string) $supportRequest->getKey())
        ->and($externalAudit->resource_id)->toBe((string) $supportRequest->getKey())
        ->and($externalAudit->managed_environment_id)->toBe((int) $tenant->getKey())
        ->and($externalAudit->status)->toBe('success')
        ->and(data_get($externalAudit->metadata, 'internal_reference'))->toBe($supportRequest->internal_reference)
        ->and(data_get($externalAudit->metadata, 'external_handoff_mode'))->toBe(SupportRequest::EXTERNAL_HANDOFF_MODE_CREATE_EXTERNAL_TICKET)
        ->and(data_get($externalAudit->metadata, 'external_ticket_reference'))->toBe('PSA-AUDIT-CREATED')
        ->and((string) json_encode($externalAudit->metadata))->not->toContain('must-not-be-copied');
});

it('records external ticket linked audit without issuing outbound create', function (): void {
    spec256ConfigureAuditSupportDesk();

    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'operator');

    Http::fake();

    spec256AuditTenantComponent($user, $tenant)
        ->mountAction('requestSupport')
        ->setActionData([
            'summary' => 'Audit external ticket linked.',
            'external_handoff_mode' => SupportRequest::EXTERNAL_HANDOFF_MODE_LINK_EXISTING_TICKET,
            'external_ticket_reference' => 'PSA-AUDIT-LINKED',
        ])
        ->callMountedAction()
        ->assertHasNoActionErrors();

    $externalAudit = AuditLog::query()
        ->where('action', AuditActionId::SupportRequestExternalTicketLinked->value)
        ->sole();

    expect(data_get($externalAudit->metadata, 'external_handoff_mode'))->toBe(SupportRequest::EXTERNAL_HANDOFF_MODE_LINK_EXISTING_TICKET)
        ->and(data_get($externalAudit->metadata, 'external_ticket_reference'))->toBe('PSA-AUDIT-LINKED')
        ->and($externalAudit->status)->toBe('success');

    Http::assertNothingSent();
});

it('records external handoff failed audit with bounded failure metadata', function (): void {
    spec256ConfigureAuditSupportDesk();

    $tenant = ManagedEnvironment::factory()->create();
    [$user, $tenant] = createUserWithTenant(tenant: $tenant, role: 'manager');

    Http::fake([
        'desk.example.test/*' => Http::failedConnection(),
    ]);

    spec256AuditTenantComponent($user, $tenant)
        ->mountAction('requestSupport')
        ->setActionData([
            'summary' => 'Audit external ticket failure.',
            'external_handoff_mode' => SupportRequest::EXTERNAL_HANDOFF_MODE_CREATE_EXTERNAL_TICKET,
        ])
        ->callMountedAction()
        ->assertHasNoActionErrors();

    $supportRequest = SupportRequest::query()->sole();

    $externalAudit = AuditLog::query()
        ->where('action', AuditActionId::SupportRequestExternalHandoffFailed->value)
        ->sole();

    expect($externalAudit->resource_id)->toBe((string) $supportRequest->getKey())
        ->and($externalAudit->status)->toBe('failed')
        ->and(data_get($externalAudit->metadata, 'external_ticket_reference'))->toBeNull()
        ->and(data_get($externalAudit->metadata, 'external_handoff_failure_summary'))->toContain('configured timeout');
});
