<?php

namespace App\Filament\Resources;

use App\Enums\TenantAnnouncementAudience;
use App\Enums\TenantAnnouncementSegment;
use App\Enums\TenantAnnouncementStatus;
use App\Filament\Clusters\RareAdmin\RareAdminCluster;
use App\Filament\Resources\TenantAnnouncementResource\Pages;
use App\Models\TenantAnnouncement;
use App\Services\Audit\SuperAdminAuditLogger;
use BackedEnum;
use Filament\Actions;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Components\DateTimePicker;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Utilities\Get;
use Filament\Schemas\Schema;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Auth;
use UnitEnum;

class TenantAnnouncementResource extends Resource
{
    protected static ?string $model = TenantAnnouncement::class;

    protected static ?string $cluster = RareAdminCluster::class;

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

    protected static ?string $recordTitleAttribute = 'title';

    protected static ?int $navigationSort = 70;

    public static function getNavigationGroup(): UnitEnum|string|null
    {
        return __('admin.nav.platform');
    }

    public static function form(Schema $schema): Schema
    {
        $statusOptions = collect(TenantAnnouncementStatus::cases())
            ->mapWithKeys(fn (TenantAnnouncementStatus $status) => [$status->value => $status->label()])
            ->all();

        $audienceOptions = collect(TenantAnnouncementAudience::cases())
            ->mapWithKeys(fn (TenantAnnouncementAudience $audience) => [$audience->value => $audience->label()])
            ->all();

        $segmentOptions = collect(TenantAnnouncementSegment::cases())
            ->mapWithKeys(fn (TenantAnnouncementSegment $segment) => [$segment->value => $segment->label()])
            ->all();

        return $schema
            ->schema([
                Section::make('Inhalt')
                    ->schema([
                        TextInput::make('title')
                            ->label('Titel')
                            ->required()
                            ->maxLength(160),
                        Textarea::make('body')
                            ->label('Text')
                            ->rows(6)
                            ->required()
                            ->columnSpanFull(),
                        TextInput::make('cta_label')
                            ->label('CTA-Label')
                            ->maxLength(160),
                        TextInput::make('cta_url')
                            ->label('CTA-Link')
                            ->maxLength(255)
                            ->url()
                            ->nullable(),
                    ])
                    ->columns(2),
                Section::make('Zielgruppe')
                    ->schema([
                        Select::make('audience')
                            ->label('Zielgruppe')
                            ->options($audienceOptions)
                            ->default(TenantAnnouncementAudience::ALL->value)
                            ->live()
                            ->required(),
                        Select::make('tenants')
                            ->label('Mandanten')
                            ->relationship('tenants', 'name')
                            ->multiple()
                            ->preload()
                            ->searchable()
                            ->visible(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::TENANTS->value)
                            ->dehydrated(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::TENANTS->value)
                            ->required(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::TENANTS->value)
                            ->columnSpanFull(),
                        CheckboxList::make('segments')
                            ->label('Segmente')
                            ->options($segmentOptions)
                            ->columns(2)
                            ->default([])
                            ->visible(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::SEGMENTS->value)
                            ->dehydrated(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::SEGMENTS->value)
                            ->required(fn (Get $get): bool => $get('audience') === TenantAnnouncementAudience::SEGMENTS->value)
                            ->columnSpanFull(),
                        Toggle::make('email_enabled')
                            ->label('E-Mail versenden')
                            ->default(true),
                    ])
                    ->columns(2),
                Section::make('Zeitplan')
                    ->schema([
                        Select::make('status')
                            ->label('Status')
                            ->options($statusOptions)
                            ->default(TenantAnnouncementStatus::DRAFT->value)
                            ->live()
                            ->required(),
                        DateTimePicker::make('starts_at')
                            ->label('Startet am')
                            ->seconds(false)
                            ->nullable()
                            ->required(fn (Get $get): bool => $get('status') === TenantAnnouncementStatus::SCHEDULED->value),
                        DateTimePicker::make('ends_at')
                            ->label('Endet am')
                            ->seconds(false)
                            ->nullable(),
                    ])
                    ->columns(2),
            ])
            ->columns(1);
    }

    public static function table(Table $table): Table
    {
        $statusOptions = collect(TenantAnnouncementStatus::cases())
            ->mapWithKeys(fn (TenantAnnouncementStatus $status) => [$status->value => $status->label()])
            ->all();

        $audienceOptions = collect(TenantAnnouncementAudience::cases())
            ->mapWithKeys(fn (TenantAnnouncementAudience $audience) => [$audience->value => $audience->label()])
            ->all();

        return $table
            ->columns([
                Tables\Columns\TextColumn::make('title')
                    ->label('Titel')
                    ->searchable()
                    ->sortable()
                    ->limit(50),
                Tables\Columns\TextColumn::make('status')
                    ->label('Status')
                    ->badge()
                    ->formatStateUsing(function ($state): string {
                        if ($state instanceof TenantAnnouncementStatus) {
                            return $state->label();
                        }

                        return TenantAnnouncementStatus::tryFrom((string) $state)?->label() ?? (string) $state;
                    })
                    ->sortable(),
                Tables\Columns\TextColumn::make('audience')
                    ->label('Zielgruppe')
                    ->badge()
                    ->formatStateUsing(function ($state): string {
                        if ($state instanceof TenantAnnouncementAudience) {
                            return $state->label();
                        }

                        return TenantAnnouncementAudience::tryFrom((string) $state)?->label() ?? (string) $state;
                    })
                    ->sortable(),
                Tables\Columns\IconColumn::make('email_enabled')
                    ->label('E-Mail')
                    ->boolean(),
                Tables\Columns\TextColumn::make('starts_at')
                    ->label('Start')
                    ->dateTime()
                    ->sortable(),
                Tables\Columns\TextColumn::make('ends_at')
                    ->label('Ende')
                    ->dateTime()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                Tables\Columns\TextColumn::make('updated_at')
                    ->label('Aktualisiert')
                    ->since()
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                Tables\Filters\SelectFilter::make('status')
                    ->label('Status')
                    ->options($statusOptions),
                Tables\Filters\SelectFilter::make('audience')
                    ->label('Zielgruppe')
                    ->options($audienceOptions),
            ])
            ->actions([
                Actions\EditAction::make()
                    ->after(fn (array $data, TenantAnnouncement $record) => app(SuperAdminAuditLogger::class)->recordModelMutation(
                        'updated',
                        $record,
                        SuperAdminAuditLogger::fieldsMetadata($data),
                        static::class
                    )),
            ])
            ->bulkActions([
                Actions\DeleteBulkAction::make()
                    ->after(function (Collection $records): void {
                        $logger = app(SuperAdminAuditLogger::class);

                        foreach ($records as $record) {
                            $logger->recordModelMutation(
                                'deleted',
                                $record,
                                source: static::class
                            );
                        }
                    }),
            ]);
    }

    public static function getPages(): array
    {
        return [
            'index' => Pages\ListTenantAnnouncements::route('/'),
            'create' => Pages\CreateTenantAnnouncement::route('/create'),
            'edit' => Pages\EditTenantAnnouncement::route('/{record}/edit'),
        ];
    }

    public static function mutateFormDataBeforeCreate(array $data): array
    {
        if ($userId = Auth::id()) {
            $data['created_by'] = $userId;
            $data['updated_by'] = $userId;
        }

        return $data;
    }

    public static function mutateFormDataBeforeSave(array $data): array
    {
        if ($userId = Auth::id()) {
            $data['updated_by'] = $userId;
        }

        return $data;
    }
}
