<?php

declare(strict_types=1);

namespace App\Filament\Widgets\Dashboard;

use App\Filament\Resources\FindingResource;
use App\Models\Finding;
use App\Models\InventoryItem;
use App\Models\Tenant;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\OpsUx\ActiveRuns;
use Filament\Facades\Filament;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Table;
use Filament\Widgets\TableWidget;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Arr;

class RecentDriftFindings extends TableWidget
{
    protected int|string|array $columnSpan = 'full';

    public function table(Table $table): Table
    {
        $tenant = Filament::getTenant();

        return $table
            ->heading('Recent Drift Findings')
            ->query($this->getQuery())
            ->poll(fn (): ?string => ($tenant instanceof Tenant) && ActiveRuns::existForTenant($tenant) ? '10s' : null)
            ->defaultSort('created_at', 'desc')
            ->paginated(\App\Support\Filament\TablePaginationProfiles::widget())
            ->columns([
                TextColumn::make('short_id')
                    ->label('ID')
                    ->state(fn (Finding $record): string => '#'.$record->getKey())
                    ->copyable()
                    ->copyableState(fn (Finding $record): string => (string) $record->getKey()),
                TextColumn::make('subject_display_name')
                    ->label('Subject')
                    ->placeholder('—')
                    ->limit(40)
                    ->formatStateUsing(function (?string $state, Finding $record): ?string {
                        if (is_string($state) && trim($state) !== '') {
                            return $state;
                        }

                        $fallback = Arr::get($record->evidence_jsonb ?? [], 'display_name');
                        $fallback = is_string($fallback) ? trim($fallback) : null;

                        return $fallback !== '' ? $fallback : null;
                    })
                    ->description(function (Finding $record): ?string {
                        if (Arr::get($record->evidence_jsonb ?? [], 'summary.kind') !== 'rbac_role_definition') {
                            return null;
                        }

                        return __('findings.drift.rbac_role_definition');
                    })
                    ->tooltip(function (Finding $record): ?string {
                        $displayName = $record->subject_display_name;

                        if (is_string($displayName) && trim($displayName) !== '') {
                            return $displayName;
                        }

                        $fallback = Arr::get($record->evidence_jsonb ?? [], 'display_name');

                        return is_string($fallback) && trim($fallback) !== '' ? trim($fallback) : null;
                    }),
                TextColumn::make('severity')
                    ->badge()
                    ->sortable()
                    ->formatStateUsing(BadgeRenderer::label(BadgeDomain::FindingSeverity))
                    ->color(BadgeRenderer::color(BadgeDomain::FindingSeverity))
                    ->icon(BadgeRenderer::icon(BadgeDomain::FindingSeverity))
                    ->iconColor(BadgeRenderer::iconColor(BadgeDomain::FindingSeverity)),
                TextColumn::make('status')
                    ->badge()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true)
                    ->formatStateUsing(BadgeRenderer::label(BadgeDomain::FindingStatus))
                    ->color(BadgeRenderer::color(BadgeDomain::FindingStatus))
                    ->icon(BadgeRenderer::icon(BadgeDomain::FindingStatus))
                    ->iconColor(BadgeRenderer::iconColor(BadgeDomain::FindingStatus)),
                TextColumn::make('created_at')
                    ->label('Created')
                    ->sortable()
                    ->since(),
            ])
            ->recordUrl(fn (Finding $record): ?string => $tenant instanceof Tenant
                ? FindingResource::getUrl('view', ['record' => $record], tenant: $tenant)
                : null)
            ->emptyStateHeading('No drift findings')
            ->emptyStateDescription('You\'re looking good — no drift findings to review yet.');
    }

    /**
     * @return Builder<Finding>
     */
    private function getQuery(): Builder
    {
        $tenant = Filament::getTenant();
        $tenantId = $tenant instanceof Tenant ? $tenant->getKey() : null;

        return Finding::query()
            ->addSelect([
                'subject_display_name' => InventoryItem::query()
                    ->select('display_name')
                    ->whereColumn('inventory_items.tenant_id', 'findings.tenant_id')
                    ->whereColumn('inventory_items.external_id', 'findings.subject_external_id')
                    ->limit(1),
            ])
            ->when($tenantId, fn (Builder $query) => $query->where('tenant_id', $tenantId))
            ->where('finding_type', Finding::FINDING_TYPE_DRIFT)
            ->latest('created_at');
    }
}
