<?php

namespace App\Filament\Clusters\WeeklyOps\Resources\TaskCollections;

use App\Filament\Clusters\WeeklyOps\Resources\TaskCollections\Pages\CreateTaskCollection;
use App\Filament\Clusters\WeeklyOps\Resources\TaskCollections\Pages\EditTaskCollection;
use App\Filament\Clusters\WeeklyOps\Resources\TaskCollections\Pages\ListTaskCollections;
use App\Filament\Clusters\WeeklyOps\Resources\TaskCollections\RelationManagers\TasksRelationManager;
use App\Filament\Clusters\WeeklyOps\WeeklyOpsCluster;
use App\Models\EventType;
use App\Models\TaskCollection;
use App\Services\Audit\SuperAdminAuditLogger;
use BackedEnum;
use Filament\Actions;
use Filament\Forms\Components\MarkdownEditor;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Toggle;
use Filament\Resources\Resource;
use Filament\Schemas\Components\Tabs as SchemaTabs;
use Filament\Schemas\Components\Tabs\Tab as SchemaTab;
use Filament\Schemas\Schema;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use UnitEnum;

class TaskCollectionResource extends Resource
{
    protected static ?string $model = TaskCollection::class;

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

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

    protected static ?string $recordTitleAttribute = 'name';

    protected static ?int $navigationSort = 31;

    public static function form(Schema $schema): Schema
    {
        return $schema
            ->schema([
                TextInput::make('slug')
                    ->label(__('admin.common.slug'))
                    ->maxLength(255)
                    ->unique(ignoreRecord: true)
                    ->required(),
                Select::make('event_type_id')
                    ->relationship('eventType', 'name')
                    ->getOptionLabelFromRecordUsing(fn (EventType $record) => is_array($record->name) ? ($record->name['de'] ?? $record->name['en'] ?? __('admin.common.unnamed')) : $record->name)
                    ->searchable()
                    ->preload()
                    ->label(__('admin.task_collections.fields.event_type_optional')),
                SchemaTabs::make('content_tabs')
                    ->label(__('admin.task_collections.fields.content_localization'))
                    ->tabs([
                        SchemaTab::make(__('admin.common.german'))
                            ->icon('heroicon-o-language')
                            ->schema([
                                TextInput::make('name_translations.de')
                                    ->label(__('admin.task_collections.fields.name_de'))
                                    ->required(),
                                MarkdownEditor::make('description_translations.de')
                                    ->label(__('admin.task_collections.fields.description_de'))
                                    ->columnSpanFull(),
                            ]),
                        SchemaTab::make(__('admin.common.english'))
                            ->icon('heroicon-o-language')
                            ->schema([
                                TextInput::make('name_translations.en')
                                    ->label(__('admin.task_collections.fields.name_en'))
                                    ->required(),
                                MarkdownEditor::make('description_translations.en')
                                    ->label(__('admin.task_collections.fields.description_en'))
                                    ->columnSpanFull(),
                            ]),
                    ])
                    ->columnSpanFull(),
                Toggle::make('is_default')
                    ->label(__('admin.task_collections.fields.is_default'))
                    ->default(false),
                TextInput::make('position')
                    ->label(__('admin.task_collections.fields.position'))
                    ->numeric()
                    ->default(0),
            ])
            ->columns(2);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                TextColumn::make('id')
                    ->label('#')
                    ->sortable(),
                TextColumn::make('name')
                    ->label(__('admin.task_collections.table.name'))
                    ->getStateUsing(fn (TaskCollection $record) => static::formatTranslation($record->name_translations))
                    ->searchable(['name_translations->de', 'name_translations->en'])
                    ->limit(60),
                TextColumn::make('eventType.name')
                    ->label(__('admin.task_collections.table.event_type'))
                    ->getStateUsing(function (TaskCollection $record) {
                        $value = optional($record->eventType)->name;

                        if (is_array($value)) {
                            $locale = app()->getLocale();

                            return $value[$locale] ?? ($value['de'] ?? ($value['en'] ?? ''));
                        }

                        return (string) ($value ?? '');
                    })
                    ->toggleable(),
                TextColumn::make('slug')
                    ->label(__('admin.task_collections.table.slug'))
                    ->toggleable()
                    ->searchable(),
                IconColumn::make('is_default')
                    ->label(__('admin.task_collections.table.is_default'))
                    ->boolean(),
                TextColumn::make('position')
                    ->label(__('admin.task_collections.table.position'))
                    ->sortable(),
                TextColumn::make('tasks_count')
                    ->label(__('admin.task_collections.table.tasks'))
                    ->sortable(),
                TextColumn::make('events_count')
                    ->label(__('admin.task_collections.table.events'))
                    ->sortable(),
            ])
            ->filters([
                SelectFilter::make('event_type_id')
                    ->label(__('admin.task_collections.table.event_type'))
                    ->relationship(
                        'eventType',
                        'name',
                        fn (Builder $query): Builder => $query->orderBy('name->de')
                    )
                    ->getOptionLabelFromRecordUsing(fn (EventType $record) => is_array($record->name) ? ($record->name['de'] ?? $record->name['en'] ?? __('admin.common.unnamed')) : $record->name),
                SelectFilter::make('is_default')
                    ->label(__('admin.task_collections.table.is_default'))
                    ->options([
                        '1' => __('admin.common.yes'),
                        '0' => __('admin.common.no'),
                    ]),
            ])
            ->recordActions([
                Actions\EditAction::make()
                    ->mutateDataUsing(fn (array $data, TaskCollection $record): array => static::normalizeData($data, $record))
                    ->after(fn (array $data, TaskCollection $record) => app(SuperAdminAuditLogger::class)->recordModelMutation(
                        'updated',
                        $record,
                        SuperAdminAuditLogger::fieldsMetadata($data),
                        static::class
                    )),
                Actions\DeleteAction::make()
                    ->after(fn (TaskCollection $record) => app(SuperAdminAuditLogger::class)->recordModelMutation(
                        'deleted',
                        $record,
                        source: 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 getNavigationLabel(): string
    {
        return __('admin.task_collections.menu');
    }

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

    public static function getEloquentQuery(): Builder
    {
        return parent::getEloquentQuery()
            ->whereNull('tenant_id')
            ->with('eventType')
            ->withCount(['tasks', 'events']);
    }

    /**
     * @param  array<string, mixed>  $data
     */
    public static function normalizeData(array $data, ?TaskCollection $record = null): array
    {
        $data['tenant_id'] = null;
        $data['slug'] = static::resolveSlug($data, $record);

        return $data;
    }

    /**
     * @param  array<string, mixed>  $data
     */
    protected static function resolveSlug(array $data, ?TaskCollection $record = null): string
    {
        $rawSlug = trim((string) ($data['slug'] ?? ''));
        $translations = Arr::wrap($data['name_translations'] ?? []);
        $fallbackName = (string) ($translations['en'] ?? $translations['de'] ?? '');

        $base = $rawSlug !== '' ? $rawSlug : $fallbackName;
        $slugBase = Str::slug($base) ?: 'collection';

        $query = TaskCollection::query()->where('slug', $slugBase);

        if ($record) {
            $query->whereKeyNot($record->getKey());
        }

        if (! $query->exists()) {
            return $slugBase;
        }

        do {
            $candidate = $slugBase.'-'.Str::random(4);
            $candidateQuery = TaskCollection::query()->where('slug', $candidate);

            if ($record) {
                $candidateQuery->whereKeyNot($record->getKey());
            }
        } while ($candidateQuery->exists());

        return $candidate;
    }

    /**
     * @param  array<string, string>|null  $translations
     */
    protected static function formatTranslation(?array $translations): string
    {
        if (! is_array($translations)) {
            return '';
        }

        $locale = app()->getLocale();

        return $translations[$locale]
            ?? ($translations['de'] ?? ($translations['en'] ?? Arr::first($translations) ?? ''));
    }

    public static function getPages(): array
    {
        return [
            'index' => ListTaskCollections::route('/'),
            'create' => CreateTaskCollection::route('/create'),
            'edit' => EditTaskCollection::route('/{record}/edit'),
        ];
    }

    public static function getRelations(): array
    {
        return [
            TasksRelationManager::class,
        ];
    }
}
