<?php

namespace App\Filament\Resources;

use App\Filament\Clusters\WeeklyOps\WeeklyOpsCluster;
use App\Filament\Resources\PackageResource\Pages;
use App\Jobs\PullPackageFromPaddle;
use App\Jobs\SyncPackageToPaddle;
use App\Models\Package;
use App\Services\Audit\SuperAdminAuditLogger;
use BackedEnum;
use Filament\Actions;
use Filament\Actions\BulkActionGroup;
use Filament\Actions\DeleteAction;
use Filament\Actions\DeleteBulkAction;
use Filament\Actions\EditAction;
use Filament\Actions\ForceDeleteAction;
use Filament\Actions\ForceDeleteBulkAction;
use Filament\Actions\RestoreAction;
use Filament\Actions\RestoreBulkAction;
use Filament\Actions\ViewAction;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Components\Placeholder;
use Filament\Forms\Components\Repeater;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Notifications\Notification;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Section;
use Filament\Schemas\Components\Tabs as SchemaTabs;
use Filament\Schemas\Components\Tabs\Tab as SchemaTab;
use Filament\Schemas\Schema;
use Filament\Tables;
use Filament\Tables\Columns\BadgeColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\TrashedFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Support\Str;
use Illuminate\Validation\Rules\Unique;
use UnitEnum;

class PackageResource extends Resource
{
    protected static ?string $model = Package::class;

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

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

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

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

    protected static ?int $navigationSort = 5;

    public static function form(Schema $schema): Schema
    {
        $featureOptions = static::featureLabelMap();

        return $schema->schema([
            SchemaTabs::make('translations')
                ->columnSpanFull()
                ->tabs([
                    SchemaTab::make('Deutsch')
                        ->schema([
                            TextInput::make('name_translations.de')
                                ->label('Name (DE)')
                                ->required()
                                ->maxLength(255),
                            MarkdownEditor::make('description_translations.de')
                                ->label('Beschreibung (DE)')
                                ->required()
                                ->columnSpanFull(),
                        ]),
                    SchemaTab::make('English')
                        ->schema([
                            TextInput::make('name_translations.en')
                                ->label('Name (EN)')
                                ->required()
                                ->maxLength(255),
                            MarkdownEditor::make('description_translations.en')
                                ->label('Description (EN)')
                                ->required()
                                ->columnSpanFull(),
                        ]),
                ]),
            Section::make('Allgemeine Einstellungen')
                ->columns(3)
                ->schema([
                    TextInput::make('slug')
                        ->label('Slug')
                        ->required()
                        ->maxLength(191)
                        ->unique(
                            ignoreRecord: true,
                            modifyRuleUsing: fn (Unique $rule) => $rule->withoutTrashed()
                        ),
                    Select::make('type')
                        ->label('Paket-Typ')
                        ->options([
                            'endcustomer' => 'Endkunde',
                            'reseller' => 'Reseller',
                        ])
                        ->required(),
                    TextInput::make('price')
                        ->label('Preis')
                        ->numeric()
                        ->step(0.01)
                        ->prefix('€')
                        ->required(),
                    TextInput::make('max_photos')
                        ->label('Max. Fotos')
                        ->numeric()
                        ->minValue(0)
                        ->nullable(),
                    TextInput::make('max_guests')
                        ->label('Max. Gäste')
                        ->numeric()
                        ->minValue(0)
                        ->nullable(),
                    TextInput::make('gallery_days')
                        ->label('Galeriedauer (Tage)')
                        ->numeric()
                        ->minValue(0)
                        ->nullable(),
                    TextInput::make('max_tasks')
                        ->label('Max. Fotoaufgaben')
                        ->numeric()
                        ->minValue(0)
                        ->nullable(),
                    TextInput::make('max_events_per_year')
                        ->label('Events pro Jahr')
                        ->numeric()
                        ->minValue(0)
                        ->nullable()
                        ->visible(fn ($get) => $get('type') === 'reseller'),
                    Toggle::make('watermark_allowed')
                        ->label('Eigenes Wasserzeichen erlaubt')
                        ->default(true),
                    Toggle::make('branding_allowed')
                        ->label('Eigenes Branding erlaubt')
                        ->default(false),
                ]),
            Section::make('Features & Kennzahlen')
                ->columns(1)
                ->schema([
                    CheckboxList::make('features')
                        ->label('Aktive Features')
                        ->options($featureOptions)
                        ->columns(2)
                        ->default([]),
                    Repeater::make('description_table')
                        ->label('Kenndaten')
                        ->schema([
                            TextInput::make('title')
                                ->label('Titel')
                                ->maxLength(255),
                            TextInput::make('value')
                                ->label('Wert / Beschreibung')
                                ->maxLength(255),
                        ])
                        ->addActionLabel('Eintrag hinzufügen')
                        ->reorderable()
                        ->columnSpanFull()
                        ->default([]),
                ]),
            Section::make('Paddle Billing')
                ->columns(2)
                ->schema([
                    TextInput::make('paddle_product_id')
                        ->label('Paddle Produkt-ID')
                        ->maxLength(191)
                        ->helperText('Produkt aus Paddle Billing. Leer lassen, wenn noch nicht synchronisiert.')
                        ->placeholder('nicht verknüpft'),
                    TextInput::make('paddle_price_id')
                        ->label('Paddle Preis-ID')
                        ->maxLength(191)
                        ->helperText('Preis-ID aus Paddle Billing, verknüpft mit diesem Paket.')
                        ->placeholder('nicht verknüpft'),
                    Placeholder::make('paddle_sync_status')
                        ->label('Sync-Status')
                        ->content(fn (?Package $record) => $record?->paddle_sync_status ? Str::headline($record->paddle_sync_status) : '–')
                        ->columnSpanFull(),
                    Placeholder::make('paddle_synced_at')
                        ->label('Zuletzt synchronisiert')
                        ->content(fn (?Package $record) => $record?->paddle_synced_at ? $record->paddle_synced_at->diffForHumans() : '–')
                        ->columnSpanFull(),
                    Placeholder::make('paddle_sync_error')
                        ->label('Letzter Fehler')
                        ->content(fn (?Package $record) => $record?->paddle_sync_error_message ?? '–')
                        ->visible(fn (?Package $record) => filled($record?->paddle_sync_error_message))
                        ->columnSpanFull(),
                ]),
        ]);
    }

    public static function formatFeaturesForDisplay(mixed $features): string
    {
        if (is_string($features)) {
            $decoded = json_decode($features, true);
            if (json_last_error() === JSON_ERROR_NONE) {
                $features = $decoded;
            }
        }

        if (! is_array($features)) {
            return '';
        }

        $labels = static::featureLabelMap();

        if (array_is_list($features)) {
            return collect($features)
                ->filter(fn ($value) => is_string($value) && $value !== '')
                ->map(fn ($value) => $labels[$value] ?? $value)
                ->implode(', ');
        }

        return collect($features)
            ->filter(fn ($value) => (bool) $value)
            ->keys()
            ->map(fn ($value) => $labels[$value] ?? $value)
            ->implode(', ');
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                TextColumn::make('name_translations.de')
                    ->label('Name (DE)')
                    ->searchable()
                    ->sortable(),
                TextColumn::make('name_translations.en')
                    ->label('Name (EN)')
                    ->toggleable(isToggledHiddenByDefault: true),
                BadgeColumn::make('type')
                    ->label('Typ')
                    ->colors([
                        'info' => 'endcustomer',
                        'warning' => 'reseller',
                    ]),
                TextColumn::make('price')
                    ->label('Preis')
                    ->money('EUR')
                    ->sortable(),
                TextColumn::make('max_photos')
                    ->label('Fotos')
                    ->sortable(),
                TextColumn::make('max_guests')
                    ->label('Gäste')
                    ->sortable()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('features')
                    ->label('Features')
                    ->wrap()
                    ->formatStateUsing(fn ($state) => static::formatFeaturesForDisplay($state)),
                TextColumn::make('paddle_product_id')
                    ->label('Paddle Produkt')
                    ->toggleable(isToggledHiddenByDefault: true)
                    ->formatStateUsing(fn ($state) => $state ?: '-'),
                TextColumn::make('paddle_price_id')
                    ->label('Paddle Preis')
                    ->toggleable(isToggledHiddenByDefault: true)
                    ->formatStateUsing(fn ($state) => $state ?: '-'),
                BadgeColumn::make('paddle_sync_status')
                    ->label('Sync-Status')
                    ->colors([
                        'success' => 'synced',
                        'warning' => 'syncing',
                        'info' => ['dry-run', 'linked', 'pulled'],
                        'danger' => ['failed', 'pull-failed'],
                    ])
                    ->formatStateUsing(fn ($state) => $state ? Str::headline($state) : null)
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_synced_at')
                    ->label('Sync am')
                    ->dateTime()
                    ->toggleable(isToggledHiddenByDefault: true),
                TextColumn::make('paddle_sync_error_message')
                    ->label('Sync-Fehler')
                    ->getStateUsing(fn (Package $record) => $record->paddle_sync_error_message)
                    ->wrap()
                    ->toggleable(isToggledHiddenByDefault: true),
            ])
            ->filters([
                Tables\Filters\SelectFilter::make('type')
                    ->label('Typ')
                    ->options([
                        'endcustomer' => 'Endkunde',
                        'reseller' => 'Reseller',
                    ]),
                TrashedFilter::make(),
            ])
            ->actions([
                Actions\Action::make('syncPaddle')
                    ->label('Mit Paddle abgleichen')
                    ->icon('heroicon-o-cloud-arrow-up')
                    ->color('success')
                    ->requiresConfirmation()
                    ->disabled(fn (Package $record) => $record->paddle_sync_status === 'syncing')
                    ->action(function (Package $record) {
                        SyncPackageToPaddle::dispatch($record->id);

                        Notification::make()
                            ->success()
                            ->title('Paddle-Sync gestartet')
                            ->body('Das Paket wird im Hintergrund mit Paddle abgeglichen.')
                            ->send();
                    }),
                Actions\Action::make('linkPaddle')
                    ->label('Paddle verknüpfen')
                    ->icon('heroicon-o-link')
                    ->color('info')
                    ->form([
                        TextInput::make('paddle_product_id')
                            ->label('Paddle Produkt-ID')
                            ->required()
                            ->maxLength(191),
                        TextInput::make('paddle_price_id')
                            ->label('Paddle Preis-ID')
                            ->required()
                            ->maxLength(191),
                    ])
                    ->fillForm(fn (Package $record) => [
                        'paddle_product_id' => $record->paddle_product_id,
                        'paddle_price_id' => $record->paddle_price_id,
                    ])
                    ->action(function (Package $record, array $data): void {
                        $record->linkPaddleIds($data['paddle_product_id'], $data['paddle_price_id']);

                        PullPackageFromPaddle::dispatch($record->id);

                        app(SuperAdminAuditLogger::class)->recordModelMutation(
                            'linked',
                            $record,
                            SuperAdminAuditLogger::fieldsMetadata($data),
                            static::class
                        );

                        Notification::make()
                            ->success()
                            ->title('Paddle-Verknüpfung gespeichert')
                            ->body('Die IDs wurden gespeichert und ein Pull wurde angestoßen.')
                            ->send();
                    }),
                Actions\Action::make('pullPaddle')
                    ->label('Status von Paddle holen')
                    ->icon('heroicon-o-cloud-arrow-down')
                    ->disabled(fn (Package $record) => ! $record->paddle_product_id && ! $record->paddle_price_id)
                    ->requiresConfirmation()
                    ->action(function (Package $record) {
                        PullPackageFromPaddle::dispatch($record->id);

                        Notification::make()
                            ->info()
                            ->title('Paddle-Abgleich angefordert')
                            ->body('Der aktuelle Stand aus Paddle wird geladen und hier hinterlegt.')
                            ->send();
                    }),
                ViewAction::make(),
                EditAction::make()
                    ->after(fn (array $data, Package $record) => app(SuperAdminAuditLogger::class)->recordModelMutation(
                        'updated',
                        $record,
                        SuperAdminAuditLogger::fieldsMetadata($data),
                        static::class
                    )),
                DeleteAction::make()
                    ->visible(fn (Package $record) => ! $record->trashed())
                    ->after(fn (Package $record) => app(SuperAdminAuditLogger::class)->recordModelMutation(
                        'deleted',
                        $record,
                        source: static::class
                    )),
                RestoreAction::make()
                    ->visible(fn (Package $record) => $record->trashed())
                    ->after(fn (Package $record) => app(SuperAdminAuditLogger::class)->recordModelMutation(
                        'restored',
                        $record,
                        source: static::class
                    )),
                ForceDeleteAction::make()
                    ->visible(fn (Package $record) => $record->trashed())
                    ->requiresConfirmation()
                    ->after(fn (Package $record) => app(SuperAdminAuditLogger::class)->recordModelMutation(
                        'force_deleted',
                        $record,
                        source: static::class
                    )),
            ])
            ->bulkActions([
                BulkActionGroup::make([
                    DeleteBulkAction::make()
                        ->after(function (Collection $records): void {
                            $logger = app(SuperAdminAuditLogger::class);

                            foreach ($records as $record) {
                                $logger->recordModelMutation(
                                    'deleted',
                                    $record,
                                    source: static::class
                                );
                            }
                        }),
                    RestoreBulkAction::make()
                        ->after(function (Collection $records): void {
                            $logger = app(SuperAdminAuditLogger::class);

                            foreach ($records as $record) {
                                $logger->recordModelMutation(
                                    'restored',
                                    $record,
                                    source: static::class
                                );
                            }
                        }),
                    ForceDeleteBulkAction::make()
                        ->requiresConfirmation()
                        ->after(function (Collection $records): void {
                            $logger = app(SuperAdminAuditLogger::class);

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

    public static function getEloquentQuery(): Builder
    {
        return parent::getEloquentQuery()
            ->withoutGlobalScopes([
                SoftDeletingScope::class,
            ]);
    }

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

    protected static function featureLabelMap(): array
    {
        return [
            'basic_uploads' => 'Basis-Uploads',
            'limited_sharing' => 'Begrenztes Teilen',
            'unlimited_sharing' => 'Unbegrenztes Teilen',
            'no_watermark' => 'Kein Wasserzeichen',
            'custom_branding' => 'Eigenes Branding',
            'custom_tasks' => 'Eigene Aufgaben',
            'reseller_dashboard' => 'Reseller-Dashboard',
            'advanced_analytics' => 'Erweiterte Analytics',
            'advanced_reporting' => 'Erweiterte Reports',
            'live_slideshow' => 'Live-Slideshow',
            'priority_support' => 'Priorisierter Support',
        ];
    }
}
