<?php

declare(strict_types=1);

namespace App\Filament\Widgets\Inventory;

use App\Filament\Concerns\ResolvesPanelTenantContext;
use App\Models\OperationRun;
use App\Models\ManagedEnvironment;
use App\Models\User;
use App\Support\Auth\Capabilities;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Inventory\InventoryKpiBadges;
use App\Support\Inventory\TenantCoverageTruth;
use App\Support\Inventory\TenantCoverageTruthResolver;
use App\Support\OperationCatalog;
use App\Support\OperationRunLinks;
use App\Support\OperationRunType;
use App\Support\OpsUx\ActiveRuns;
use App\Support\OpsUx\OpsUxBrowserEvents;
use Filament\Widgets\StatsOverviewWidget;
use Filament\Widgets\StatsOverviewWidget\Stat;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\HtmlString;
use Livewire\Attributes\On;

class InventoryKpiHeader extends StatsOverviewWidget
{
    use ResolvesPanelTenantContext;

    protected static bool $isLazy = false;

    protected int|string|array $columnSpan = 'full';

    protected function getPollingInterval(): ?string
    {
        $tenant = static::resolveTenantContextForCurrentPanel();

        if (! $tenant instanceof ManagedEnvironment) {
            return null;
        }

        return ActiveRuns::countForTenantId((int) $tenant->getKey()) > 0 ? '10s' : null;
    }

    #[On(OpsUxBrowserEvents::RunEnqueued)]
    public function onRunEnqueued(?int $tenantId = null): void
    {
        $tenant = static::resolveTenantContextForCurrentPanel();

        if ($tenantId !== null && $tenant instanceof ManagedEnvironment && (int) $tenant->getKey() !== (int) $tenantId) {
            return;
        }
    }

    /**
     * @return array<Stat>
     */
    protected function getStats(): array
    {
        $tenant = static::resolveTenantContextForCurrentPanel();

        if (! $tenant instanceof ManagedEnvironment) {
            return [
                Stat::make('Total items', 0),
                Stat::make('Covered types', '—')->description('Select a tenant to load coverage truth.'),
                Stat::make('Need follow-up', '—')->description('Select a tenant to review follow-up types.'),
                Stat::make('Coverage basis', '—')->description('Select a tenant to see the latest coverage basis.'),
                Stat::make('Active ops', 0),
            ];
        }

        $truth = app(TenantCoverageTruthResolver::class)->resolve($tenant);

        $activeOps = ActiveRuns::countForTenantId((int) $tenant->getKey());

        $inventoryOps = (int) ActiveRuns::queryForTenantId((int) $tenant->getKey())
            ->whereIn('type', OperationCatalog::rawValuesForCanonical(OperationRunType::InventorySync->value))
            ->count();

        return [
            Stat::make('Total items', $truth->observedItemTotal)
                ->description(sprintf('Observed across %d supported types.', $truth->observedTypeCount())),
            Stat::make('Covered types', sprintf('%d / %d', $truth->succeededTypeCount, $truth->supportedTypeCount))
                ->description(new HtmlString(InventoryKpiBadges::coverageBreakdown(
                    $truth->failedTypeCount,
                    $truth->skippedTypeCount,
                    $truth->unknownTypeCount,
                ))),
            Stat::make('Need follow-up', $truth->followUpTypeCount)
                ->description(new HtmlString(InventoryKpiBadges::followUpSummary(
                    $truth->topPriorityFollowUpRow(),
                    $truth->observedItemTotal,
                    $truth->observedTypeCount(),
                ))),
            $this->coverageBasisStat($truth, $tenant),
            Stat::make('Active ops', $activeOps)
                ->description($inventoryOps > 0 ? 'A tenant inventory sync is queued or running.' : 'No inventory sync is currently active.'),
        ];
    }

    private function coverageBasisStat(TenantCoverageTruth $truth, ManagedEnvironment $tenant): Stat
    {
        $user = auth()->user();

        if (! $truth->basisRun instanceof OperationRun) {
            return Stat::make('Coverage basis', 'No current result')
                ->description($user instanceof User && $user->can(Capabilities::TENANT_INVENTORY_SYNC_RUN, $tenant)
                    ? 'Run Inventory Sync from Inventory Items to establish current coverage truth.'
                    : 'A tenant operator with inventory sync permission must establish current coverage truth.');
        }

        $outcomeBadge = BadgeRenderer::spec(BadgeDomain::OperationRunOutcome, (string) $truth->basisRun->outcome);
        $canViewRun = $user instanceof User && $user->can('view', $truth->basisRun);

        $description = Blade::render(<<<'BLADE'
            <div class="flex flex-wrap items-center gap-2">
                <x-filament::badge :color="$badgeColor" size="sm">
                    {{ $statusLabel }}
                </x-filament::badge>

                @if ($canViewRun && $viewUrl)
                    <x-filament::link :href="$viewUrl" size="sm">
                        Open basis run
                    </x-filament::link>
                @else
                    <span class="text-xs text-gray-600 dark:text-gray-300">
                        Latest run detail is not available with your current role.
                    </span>
                @endif
            </div>
            BLADE, [
            'badgeColor' => $outcomeBadge->color,
            'statusLabel' => $outcomeBadge->label,
            'canViewRun' => $canViewRun,
            'viewUrl' => $canViewRun ? OperationRunLinks::view($truth->basisRun, $tenant) : null,
        ]);

        return Stat::make('Coverage basis', $truth->basisCompletedAtLabel() ?? 'Completed')
            ->description(new HtmlString($description));
    }
}
