<?php

namespace App\Filament\Resources;

use App\Filament\Resources\EntraGroupResource\Pages;
use App\Models\EntraGroup;
use App\Models\Tenant;
use App\Support\Badges\BadgeDomain;
use App\Support\Badges\BadgeRenderer;
use App\Support\Filament\TablePaginationProfiles;
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 BackedEnum;
use Filament\Infolists\Components\TextEntry;
use Filament\Infolists\Components\ViewEntry;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Schema;
use Filament\Tables;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use UnitEnum;

class EntraGroupResource extends Resource
{
    protected static bool $isScopedToTenant = false;

    protected static ?string $model = EntraGroup::class;

    protected static string|BackedEnum|null $navigationIcon = 'heroicon-o-user-group';

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

    protected static ?string $navigationLabel = 'Groups';

    public static function actionSurfaceDeclaration(): ActionSurfaceDeclaration
    {
        return ActionSurfaceDeclaration::forResource(ActionSurfaceProfile::ListOnlyReadOnly)
            ->exempt(ActionSurfaceSlot::ListHeader, 'Directory groups list intentionally has no header actions; sync is started from the sync-runs surface.')
            ->satisfy(ActionSurfaceSlot::InspectAffordance, ActionSurfaceInspectAffordance::ClickableRow->value)
            ->exempt(ActionSurfaceSlot::ListRowMoreMenu, 'No secondary row actions are provided on this read-only list.')
            ->exempt(ActionSurfaceSlot::ListBulkMoreGroup, 'Bulk actions are intentionally omitted for directory groups.')
            ->exempt(ActionSurfaceSlot::ListEmptyState, 'Empty-state CTA is intentionally omitted; groups appear after sync.');
    }

    public static function form(Schema $schema): Schema
    {
        return $schema;
    }

    public static function infolist(Schema $schema): Schema
    {
        return $schema
            ->schema([
                Section::make('Group')
                    ->schema([
                        TextEntry::make('display_name')->label('Name'),
                        TextEntry::make('entra_id')->label('Entra ID')->copyable(),
                        TextEntry::make('type')
                            ->badge()
                            ->state(fn (EntraGroup $record): string => static::groupTypeLabel(static::groupType($record))),
                        TextEntry::make('security_enabled')
                            ->label('Security')
                            ->badge()
                            ->formatStateUsing(BadgeRenderer::label(BadgeDomain::BooleanEnabled))
                            ->color(BadgeRenderer::color(BadgeDomain::BooleanEnabled))
                            ->icon(BadgeRenderer::icon(BadgeDomain::BooleanEnabled))
                            ->iconColor(BadgeRenderer::iconColor(BadgeDomain::BooleanEnabled)),
                        TextEntry::make('mail_enabled')
                            ->label('Mail')
                            ->badge()
                            ->formatStateUsing(BadgeRenderer::label(BadgeDomain::BooleanEnabled))
                            ->color(BadgeRenderer::color(BadgeDomain::BooleanEnabled))
                            ->icon(BadgeRenderer::icon(BadgeDomain::BooleanEnabled))
                            ->iconColor(BadgeRenderer::iconColor(BadgeDomain::BooleanEnabled)),
                        TextEntry::make('last_seen_at')->label('Last seen')->dateTime()->placeholder('—'),
                    ])
                    ->columns(2)
                    ->columnSpanFull(),

                Section::make('Raw groupTypes')
                    ->schema([
                        ViewEntry::make('group_types')
                            ->label('')
                            ->view('filament.infolists.entries.snapshot-json')
                            ->state(fn (EntraGroup $record) => $record->group_types ?? [])
                            ->columnSpanFull(),
                    ])
                    ->columnSpanFull(),
            ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->defaultSort('display_name')
            ->paginated(TablePaginationProfiles::resource())
            ->persistFiltersInSession()
            ->persistSearchInSession()
            ->persistSortInSession()
            ->modifyQueryUsing(function (Builder $query): Builder {
                $tenantId = Tenant::current()?->getKey();

                return $query->when($tenantId, fn (Builder $q) => $q->where('tenant_id', $tenantId));
            })
            ->recordUrl(static fn (EntraGroup $record): ?string => static::canView($record)
                ? static::getUrl('view', ['record' => $record])
                : null)
            ->columns([
                Tables\Columns\TextColumn::make('display_name')
                    ->label('Name')
                    ->searchable()
                    ->sortable(),
                Tables\Columns\TextColumn::make('entra_id')
                    ->label('Entra ID')
                    ->copyable()
                    ->toggleable(isToggledHiddenByDefault: true),
                Tables\Columns\TextColumn::make('type')
                    ->label('Type')
                    ->badge()
                    ->state(fn (EntraGroup $record): string => static::groupTypeLabel(static::groupType($record)))
                    ->color(fn (EntraGroup $record): string => static::groupTypeColor(static::groupType($record))),
                Tables\Columns\TextColumn::make('last_seen_at')
                    ->label('Last seen')
                    ->since(),
            ])
            ->filters([
                SelectFilter::make('stale')
                    ->label('Stale')
                    ->options([
                        '1' => 'Stale',
                        '0' => 'Fresh',
                    ])
                    ->query(function (Builder $query, array $data): Builder {
                        $value = $data['value'] ?? null;

                        if ($value === null || $value === '') {
                            return $query;
                        }

                        $stalenessDays = (int) config('directory_groups.staleness_days', 30);
                        $cutoff = now('UTC')->subDays(max(1, $stalenessDays));

                        if ((string) $value === '1') {
                            return $query->where(function (Builder $q) use ($cutoff): void {
                                $q->whereNull('last_seen_at')
                                    ->orWhere('last_seen_at', '<', $cutoff);
                            });
                        }

                        return $query->where('last_seen_at', '>=', $cutoff);
                    }),
                SelectFilter::make('group_type')
                    ->label('Type')
                    ->options([
                        'security' => 'Security',
                        'microsoft365' => 'Microsoft 365',
                        'mail' => 'Mail-enabled',
                        'unknown' => 'Unknown',
                    ])
                    ->query(function (Builder $query, array $data): Builder {
                        $value = (string) ($data['value'] ?? '');

                        if ($value === '') {
                            return $query;
                        }

                        return match ($value) {
                            'microsoft365' => $query->whereJsonContains('group_types', 'Unified'),
                            'security' => $query
                                ->where('security_enabled', true)
                                ->where(function (Builder $q): void {
                                    $q->whereNull('group_types')
                                        ->orWhereJsonDoesntContain('group_types', 'Unified');
                                }),
                            'mail' => $query
                                ->where('mail_enabled', true)
                                ->where(function (Builder $q): void {
                                    $q->whereNull('group_types')
                                        ->orWhereJsonDoesntContain('group_types', 'Unified');
                                }),
                            'unknown' => $query
                                ->where(function (Builder $q): void {
                                    $q->whereNull('group_types')
                                        ->orWhereJsonDoesntContain('group_types', 'Unified');
                                })
                                ->where('security_enabled', false)
                                ->where('mail_enabled', false),
                            default => $query,
                        };
                    }),
            ])
            ->actions([])
            ->bulkActions([])
            ->emptyStateHeading('No groups cached yet')
            ->emptyStateDescription('Sync groups for the current tenant to browse directory data here.')
            ->emptyStateIcon('heroicon-o-user-group');
    }

    public static function getEloquentQuery(): Builder
    {
        return parent::getEloquentQuery()->latest('id');
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListEntraGroups::route('/'),
            'view' => Pages\ViewEntraGroup::route('/{record}'),
        ];
    }

    private static function groupType(EntraGroup $record): string
    {
        $groupTypes = $record->group_types;

        if (is_array($groupTypes) && in_array('Unified', $groupTypes, true)) {
            return 'microsoft365';
        }

        if ($record->security_enabled) {
            return 'security';
        }

        if ($record->mail_enabled) {
            return 'mail';
        }

        return 'unknown';
    }

    private static function groupTypeLabel(string $type): string
    {
        return match ($type) {
            'microsoft365' => 'Microsoft 365',
            'security' => 'Security',
            'mail' => 'Mail-enabled',
            default => 'Unknown',
        };
    }

    private static function groupTypeColor(string $type): string
    {
        return match ($type) {
            'microsoft365' => 'info',
            'security' => 'success',
            'mail' => 'warning',
            default => 'gray',
        };
    }
}
