<?php

declare(strict_types=1);

namespace App\Filament\System\Pages\Directory;

use App\Models\PlatformUser;
use App\Models\ManagedEnvironment;
use App\Services\Workspaces\WorkspaceLifecycleService;
use App\Support\Auth\PlatformCapabilities;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\System\SystemDirectoryLinks;
use App\Support\Ui\ActionSurface\ActionSurfaceDeclaration;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceInspectAffordance;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceProfile;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceSlot;
use App\Support\Ui\ActionSurface\Enums\ActionSurfaceType;
use Filament\Pages\Page;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Concerns\InteractsWithTable;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;

class Tenants extends Page implements HasTable
{
    use InteractsWithTable;

    protected static ?string $navigationLabel = 'Tenants';

    protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-users';

    protected static string|\UnitEnum|null $navigationGroup = 'Directory';

    protected static ?string $slug = 'directory/tenants';

    protected string $view = 'filament.system.pages.directory.tenants';

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forPage(ActionSurfaceProfile::ListOnlyReadOnly, ActionSurfaceType::ReadOnlyRegistryReport)
            ->exempt(ActionSurfaceSlot::ListHeader, 'System tenant directory stays scan-first and does not expose page header actions.')
            ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ClickableRow->value)
            ->exempt(ActionSurfaceSlot::ListRowMoreMenu, 'ManagedEnvironment directory rows navigate directly to the detail page and have no secondary actions.')
            ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'System tenant directory does not expose bulk actions.')
            ->satisfy(ActionSurfaceSlot::ListEmptyState, 'The empty state explains that tenants appear here after onboarding and inventory sync.');
    }

    public static function canAccess(): bool
    {
        $user = auth('platform')->user();

        return $user instanceof PlatformUser
            && $user->hasCapability(PlatformCapabilities::DIRECTORY_VIEW);
    }

    public function mount(): void
    {
        $this->mountInteractsWithTable();
    }

    public function table(Table $table): Table
    {
        return $table
            ->defaultSort('name')
            ->paginated(\App\Support\Filament\TablePaginationProfiles::customPage())
            ->query(function (): Builder {
                return ManagedEnvironment::query()
                    ->with('workspace')
                    ->withCount([
                        'providerConnections as critical_provider_connections_count' => fn (Builder $query): Builder => $query
                            ->where('provider', 'microsoft')
                            ->where('is_default', true)
                            ->whereIn('verification_status', ['blocked', 'error']),
                        'providerConnections as warning_provider_connections_count' => fn (Builder $query): Builder => $query
                            ->where('provider', 'microsoft')
                            ->where('is_default', true)
                            ->where('verification_status', 'degraded'),
                        'permissions as missing_permissions_count' => fn (Builder $query): Builder => $query->where('status', '!=', 'granted'),
                    ]);
            })
            ->columns([
                TextColumn::make('name')
                    ->label('ManagedEnvironment')
                    ->searchable()
                    ->sortable(),
                TextColumn::make('workspace.name')
                    ->label('Workspace')
                    ->searchable()
                    ->sortable(),
                TextColumn::make('status')
                    ->badge()
                    ->formatStateUsing(BadgeRenderer::label(BadgeDomain::TenantStatus))
                    ->color(BadgeRenderer::color(BadgeDomain::TenantStatus))
                    ->icon(BadgeRenderer::icon(BadgeDomain::TenantStatus))
                    ->iconColor(BadgeRenderer::iconColor(BadgeDomain::TenantStatus)),
                TextColumn::make('workspace_posture')
                    ->label('Workspace posture')
                    ->state(fn (ManagedEnvironment $record): string => app(WorkspaceLifecycleService::class)->tenantPosture($record))
                    ->badge()
                    ->formatStateUsing(BadgeRenderer::label(BadgeDomain::TenantWorkspacePosture))
                    ->color(BadgeRenderer::color(BadgeDomain::TenantWorkspacePosture))
                    ->icon(BadgeRenderer::icon(BadgeDomain::TenantWorkspacePosture))
                    ->iconColor(BadgeRenderer::iconColor(BadgeDomain::TenantWorkspacePosture)),
                TextColumn::make('health')
                    ->label('Health')
                    ->state(fn (ManagedEnvironment $record): string => $this->healthForTenant($record))
                    ->badge()
                    ->formatStateUsing(BadgeRenderer::label(BadgeDomain::SystemHealth))
                    ->color(BadgeRenderer::color(BadgeDomain::SystemHealth))
                    ->icon(BadgeRenderer::icon(BadgeDomain::SystemHealth))
                    ->iconColor(BadgeRenderer::iconColor(BadgeDomain::SystemHealth)),
            ])
            ->recordUrl(fn (ManagedEnvironment $record): string => SystemDirectoryLinks::tenantDetail($record))
            ->emptyStateHeading('No tenants found')
            ->emptyStateDescription('Tenants will appear here as inventory is onboarded.');
    }

    private function healthForTenant(ManagedEnvironment $tenant): string
    {
        if ($tenant->isRemovedFromWorkspace()) {
            return 'unknown';
        }

        if ((string) $tenant->status === ManagedEnvironment::STATUS_ARCHIVED) {
            return 'unknown';
        }

        if ((int) ($tenant->getAttribute('critical_provider_connections_count') ?? 0) > 0) {
            return 'critical';
        }

        if (
            (int) ($tenant->getAttribute('warning_provider_connections_count') ?? 0) > 0
            || (int) ($tenant->getAttribute('missing_permissions_count') ?? 0) > 0
        ) {
            return 'warn';
        }

        if ((string) $tenant->status === ManagedEnvironment::STATUS_ONBOARDING) {
            return 'warn';
        }

        return 'ok';
    }
}
