<?php

declare(strict_types=1);

use App\Filament\Resources\FindingResource;
use App\Filament\Resources\InventoryItemResource;
use App\Models\Finding;
use App\Models\InventoryItem;
use App\Models\OperationRun;
use App\Models\ManagedEnvironment;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

pest()->browser()->timeout(20_000);

uses(RefreshDatabase::class);

function operationActivityFeedbackSmokeLoginUrl(User $user, ManagedEnvironment $tenant, string $redirect = ''): string
{
    return route('admin.local.smoke-login', array_filter([
        'email' => $user->email,
        'tenant' => $tenant->external_id,
        'workspace' => $tenant->workspace->slug,
        'redirect' => $redirect,
    ], static fn (?string $value): bool => filled($value)));
}

it('keeps findings row actions reachable while the activity hint collapses and reopens within the browser session', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    InventoryItem::factory()->count(3)->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'display_name' => 'Browser Inventory Item',
        'policy_type' => 'deviceConfiguration',
        'platform' => 'windows',
        'last_seen_at' => now()->subMinute(),
    ]);

    Finding::factory()->count(5)->for($tenant)->create([
        'workspace_id' => (int) $tenant->workspace_id,
        'status' => Finding::STATUS_NEW,
    ]);

    OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'user_id' => (int) $user->getKey(),
        'type' => 'inventory_sync',
        'status' => 'running',
        'outcome' => 'pending',
        'started_at' => now()->subMinutes(2),
    ]);

    visit(operationActivityFeedbackSmokeLoginUrl($user, $tenant))
        ->waitForText($tenant->name)
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    $inventoryPage = visit(InventoryItemResource::getUrl('index', panel: 'admin', tenant: $tenant))
        ->resize(1440, 1200)
        ->assertScript('window.innerWidth >= 1400', true)
        ->waitForText('Inventory Items')
        ->waitForText('Browser Inventory Item')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    $shellGeometry = $inventoryPage->script(<<<'JS'
(() => {
    const banner = document.querySelector('[data-testid="ops-ux-activity-feedback-banner"]');
    const topbar = document.querySelector('.fi-topbar');
    const table = document.querySelector('.fi-ta');
    const tableContainer = table?.closest('.overflow-x-auto') ?? table?.parentElement ?? null;
    const contentShell = document.querySelector('.fi-page') ?? document.querySelector('.fi-main') ?? tableContainer?.parentElement ?? null;
    const main = document.querySelector('.fi-main');
    const header = banner?.querySelector('.tp-ops-activity-header') ?? null;
    const actionGroup = document.querySelector('[data-testid="ops-ux-activity-feedback-actions"]');
    const layout = banner?.querySelector('.tp-ops-activity-layout') ?? null;
    const headerCopy = banner?.querySelector('.tp-ops-activity-header-copy') ?? null;
    const title = banner?.querySelector('[data-testid="ops-ux-activity-feedback-title"]') ?? null;
    const helper = banner?.querySelector('[data-testid="ops-ux-activity-feedback-helper"]') ?? null;
    const middleColumn = banner?.querySelector('.tp-ops-activity-summary') ?? null;
    const track = banner?.querySelector('[data-testid="ops-ux-activity-feedback-track"]') ?? null;

    if (!banner || !topbar || !tableContainer || !contentShell || !actionGroup || !layout || !header || !headerCopy || !title || !helper || !middleColumn || !track) {
        return null;
    }

    const bannerRect = banner.getBoundingClientRect();
    const topbarRect = topbar.getBoundingClientRect();
    const tableRect = tableContainer.getBoundingClientRect();
    const contentShellRect = contentShell.getBoundingClientRect();
    const headerRect = header.getBoundingClientRect();
    const actionGroupRect = actionGroup.getBoundingClientRect();
    const headerCopyRect = headerCopy.getBoundingClientRect();
    const titleRect = title.getBoundingClientRect();
    const helperRect = helper.getBoundingClientRect();
    const middleRect = middleColumn.getBoundingClientRect();
    const trackRect = track.getBoundingClientRect();
    const layoutStyle = window.getComputedStyle(layout);
    const headerStyle = window.getComputedStyle(header);
    const titleStyle = window.getComputedStyle(title);
    const helperStyle = window.getComputedStyle(helper);
    const titleLineHeight = Number.parseFloat(titleStyle.lineHeight || '0');
    const helperLineHeight = Number.parseFloat(helperStyle.lineHeight || '0');

    return {
        viewportWidth: window.innerWidth,
        itemCount: banner.querySelectorAll('[data-testid="ops-ux-activity-feedback-item"]').length,
        stylesheetCount: document.styleSheets.length,
        hasThemeStylesheet: Array.from(document.styleSheets).some((sheet) => (sheet.href || '').includes('/build/assets/theme-')),
        mainClassName: main?.className ?? '',
        mainWidth: main?.getBoundingClientRect().width ?? 0,
        layoutClassName: layout.className,
        layoutDisplay: layoutStyle.display,
        layoutFlexDirection: layoutStyle.flexDirection,
        headerFlexDirection: headerStyle.flexDirection,
        bannerTop: bannerRect.top,
        topbarBottom: topbarRect.bottom,
        bannerTopGap: bannerRect.top - topbarRect.bottom,
        bannerHeight: bannerRect.height,
        bannerWidth: bannerRect.width,
        tableWidth: tableRect.width,
        contentWidth: contentShellRect.width,
        leftDelta: Math.abs(bannerRect.left - contentShellRect.left),
        rightDelta: Math.abs(bannerRect.right - contentShellRect.right),
        actionGroupRightDelta: Math.abs(bannerRect.right - actionGroupRect.right),
        summaryTopDelta: middleRect.top - headerRect.bottom,
        trackSpanRatio: middleRect.width > 0 ? trackRect.width / middleRect.width : 0,
        titleOverflows: title.scrollWidth > (title.clientWidth + 1),
        titleLineCount: titleLineHeight > 0 ? titleRect.height / titleLineHeight : 0,
        helperText: helper.textContent?.trim() ?? '',
        helperDisplay: helperStyle.display,
        helperWhiteSpace: helperStyle.whiteSpace,
        helperTextOverflow: helperStyle.textOverflow,
        helperLineClamp: helperStyle.getPropertyValue('-webkit-line-clamp'),
        helperOverflows: helper.scrollWidth > (helper.clientWidth + 1),
        helperLineCount: helperLineHeight > 0 ? helperRect.height / helperLineHeight : 0,
        headerCopyWidth: headerCopyRect.width,
        middleHeight: middleRect.height,
        actionHeight: actionGroupRect.height,
    };
})()
JS);

    expect($shellGeometry)->not->toBeNull()
        ->and($shellGeometry['viewportWidth'] ?? 0)->toBeGreaterThanOrEqual(1400)
        ->and($shellGeometry['itemCount'] ?? 0)->toBe(1)
        ->and($shellGeometry['stylesheetCount'] ?? 0)->toBeGreaterThan(0)
        ->and($shellGeometry['hasThemeStylesheet'] ?? false)->toBeTrue()
        ->and($shellGeometry['mainClassName'] ?? '')->toContain('fi-width-full')
        ->and($shellGeometry['mainWidth'] ?? 0)->toBeGreaterThanOrEqual(900)
        ->and($shellGeometry['layoutClassName'] ?? '')->toContain('tp-ops-activity-layout')
        ->and($shellGeometry['layoutClassName'] ?? '')->toContain('flex')
        ->and($shellGeometry['layoutDisplay'] ?? '')->toBe('flex')
        ->and($shellGeometry['layoutFlexDirection'] ?? '')->toBe('column')
        ->and($shellGeometry['headerFlexDirection'] ?? '')->toBe('row')
        ->and($shellGeometry['bannerTop'] ?? null)->toBeGreaterThanOrEqual($shellGeometry['topbarBottom'] ?? PHP_INT_MAX)
        ->and($shellGeometry['bannerTopGap'] ?? PHP_INT_MIN)->toBeGreaterThanOrEqual(12)
        ->and($shellGeometry['bannerWidth'] ?? 0)->toBeGreaterThan(0)
        ->and($shellGeometry['tableWidth'] ?? 0)->toBeGreaterThan(0)
        ->and($shellGeometry['contentWidth'] ?? 0)->toBeGreaterThan(0)
        ->and($shellGeometry['summaryTopDelta'] ?? PHP_INT_MIN)->toBeGreaterThanOrEqual(8)
        ->and($shellGeometry['trackSpanRatio'] ?? 0)->toBeGreaterThanOrEqual(0.72)
        ->and($shellGeometry['titleOverflows'] ?? true)->toBeFalse()
        ->and($shellGeometry['titleLineCount'] ?? PHP_INT_MAX)->toBeLessThanOrEqual(1.2)
        ->and($shellGeometry['helperText'] ?? '')->toBe('Queued and running work stays here until diagnostics are needed.')
        ->and($shellGeometry['helperDisplay'] ?? '')->not->toBe('-webkit-box')
        ->and($shellGeometry['helperWhiteSpace'] ?? '')->toBe('normal')
        ->and($shellGeometry['helperTextOverflow'] ?? '')->not->toBe('ellipsis')
        ->and($shellGeometry['helperLineClamp'] ?? '')->not->toBe('2')
        ->and($shellGeometry['helperOverflows'] ?? true)->toBeFalse()
        ->and($shellGeometry['helperLineCount'] ?? PHP_INT_MAX)->toBeLessThanOrEqual(2.2)
        ->and($shellGeometry['headerCopyWidth'] ?? 0)->toBeGreaterThanOrEqual(240)
        ->and($shellGeometry['leftDelta'] ?? PHP_INT_MAX)->toBeLessThanOrEqual(32)
        ->and($shellGeometry['rightDelta'] ?? PHP_INT_MAX)->toBeLessThanOrEqual(32)
        ->and($shellGeometry['actionGroupRightDelta'] ?? PHP_INT_MAX)->toBeLessThanOrEqual(32)
        ->and($shellGeometry['bannerHeight'] ?? 0)->toBeGreaterThanOrEqual(96)
        ->and($shellGeometry['bannerHeight'] ?? PHP_INT_MAX)->toBeLessThanOrEqual(145);

    $inventoryPage
        ->assertScript('document.documentElement.scrollWidth <= window.innerWidth', true)
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    $page = visit(FindingResource::getUrl('index', panel: 'admin', tenant: $tenant))
        ->resize(1440, 1200);

    $page
        ->waitForText('Triage all matching')
        ->waitForText('View operation')
        ->waitForText('Show all operations')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs()
        ->click('tbody tr.fi-ta-row:last-of-type [aria-label="More"]')
        ->waitForText('Triage')
        ->assertSee('Triage')
        ->click('[data-testid="ops-ux-activity-feedback-toggle"]')
        ->waitForText('Show activity')
        ->refresh()
        ->waitForText('Show activity');

    $page->script(<<<'JS'
window.dispatchEvent(new CustomEvent('ops-ux:run-enqueued', {
    detail: {
        tenantId: Number(document.querySelector('[data-testid="ops-ux-activity-feedback-root"]')?.dataset.tenantId || 0),
    },
}));
JS);

    $page
        ->waitForText('View operation')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs()
        ->assertDontSee('Show activity');
});

it('shows repo-real phased work as indeterminate activity and still opens the canonical run detail', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    InventoryItem::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'display_name' => 'Browser Progress Inventory Item',
        'policy_type' => 'deviceConfiguration',
        'platform' => 'windows',
        'last_seen_at' => now()->subMinute(),
    ]);

    $run = OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'user_id' => (int) $user->getKey(),
        'type' => 'baseline_capture',
        'status' => 'running',
        'outcome' => 'pending',
        'summary_counts' => [
            'total' => 10,
            'processed' => 4,
        ],
        'context' => [
            'baseline_capture' => [
                'evidence_capture' => [
                    'requested' => 10,
                    'succeeded' => 3,
                    'skipped' => 1,
                ],
                'resume_token' => 'resume-browser-123',
            ],
        ],
        'started_at' => now()->subMinute(),
    ]);

    visit(operationActivityFeedbackSmokeLoginUrl($user, $tenant))
        ->waitForText($tenant->name)
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    visit(InventoryItemResource::getUrl('index', panel: 'admin', tenant: $tenant))
        ->resize(1440, 1200)
        ->waitForText('Inventory Items')
        ->waitForText('Capturing evidence.')
        ->assertSee('View operation')
        ->assertDontSee('4 / 10 processed (40%)')
        ->assertScript("document.querySelector('[data-testid=\"ops-ux-activity-feedback-indeterminate\"]') !== null", true)
        ->assertScript("document.querySelector('[role=\"progressbar\"]') === null", true)
        ->click('View operation')
        ->waitForText('Operation #'.(int) $run->getKey())
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();
});

it('keeps terminal follow-up acknowledge local to the browser session and reopens for new work', function (): void {
    [$user, $tenant] = createUserWithTenant(role: 'owner');

    $failedRun = OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'user_id' => (int) $user->getKey(),
        'type' => 'inventory_sync',
        'status' => 'completed',
        'outcome' => 'failed',
        'started_at' => now()->subMinutes(3),
        'completed_at' => now()->subSeconds(8),
    ]);

    visit(operationActivityFeedbackSmokeLoginUrl($user, $tenant))
        ->waitForText($tenant->name)
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    $page = visit(InventoryItemResource::getUrl('index', panel: 'admin', tenant: $tenant))
        ->resize(1440, 1200)
        ->waitForText('Inventory Items')
        ->waitForText('Acknowledge')
        ->assertSee('Recent operation updates that may need review.')
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    $page
        ->click('[data-testid="ops-ux-activity-feedback-toggle"]')
        ->wait(1)
        ->assertScript(<<<'JS'
(() => {
    const banner = document.querySelector('[data-testid="ops-ux-activity-feedback-banner"]');

    return banner !== null && window.getComputedStyle(banner).display === 'none';
})()
JS, true)
        ->refresh()
        ->waitForText('Inventory Items')
        ->assertScript(<<<'JS'
(() => {
    const banner = document.querySelector('[data-testid="ops-ux-activity-feedback-banner"]');

    return banner !== null && window.getComputedStyle(banner).display === 'none';
})()
JS, true)
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();

    expect($failedRun->refresh()->status)->toBe('completed')
        ->and($failedRun->outcome)->toBe('failed');

    OperationRun::factory()->create([
        'managed_environment_id' => (int) $tenant->getKey(),
        'workspace_id' => (int) $tenant->workspace_id,
        'user_id' => (int) $user->getKey(),
        'type' => 'inventory_sync',
        'status' => 'running',
        'outcome' => 'pending',
        'started_at' => now()->subSeconds(10),
    ]);

    $page->script(<<<'JS'
window.dispatchEvent(new CustomEvent('ops-ux:run-enqueued', {
    detail: {
        tenantId: Number(document.querySelector('[data-testid="ops-ux-activity-feedback-root"]')?.dataset.tenantId || 0),
    },
}));
JS);

    $page
        ->waitForText('Review operations')
        ->waitForText('Acknowledge')
        ->assertScript(<<<'JS'
(() => {
    const banner = document.querySelector('[data-testid="ops-ux-activity-feedback-banner"]');

    return banner !== null && window.getComputedStyle(banner).display !== 'none';
})()
JS, true)
        ->assertNoJavaScriptErrors()
        ->assertNoConsoleLogs();
});
