<?php

namespace App\Filament\Tenant\Resources;

use App\Filament\Tenant\Resources\TaskCollectionResource\Pages;
use App\Models\Event;
use App\Models\EventType;
use App\Models\TaskCollection;
use App\Services\Tenant\TaskCollectionImportService;
use Filament\Facades\Filament;
use Filament\Schemas\Components\Section;
use Filament\Forms\Components\Select;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Components\Textarea;
use Filament\Schemas\Schema;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Actions;
use Filament\Tables\Columns\BadgeColumn;
use Filament\Tables\Columns\IconColumn;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Filters\SelectFilter;
use Filament\Tables\Table;
use Filament\Notifications\Notification;
use Illuminate\Support\Str;
use BackedEnum;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use App\Support\TenantOnboardingState;

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

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

    protected static ?int $navigationSort = 50;

    public static function shouldRegisterNavigation(): bool
    {
        return TenantOnboardingState::completed();
    }

    public static function getNavigationGroup(): string
    {
        return __('admin.nav.library');
    }

    public static function form(Schema $schema): Schema
    {
        $tenantId = auth()->user()?->tenant_id;

        return $schema->components([
            Section::make(__('Task Collection Details'))
                ->schema([
                    TextInput::make('name_translations.de')
                        ->label(__('Name (DE)'))
                        ->required()
                        ->maxLength(255)
                        ->disabled(fn (?TaskCollection $record) => $record?->tenant_id !== $tenantId && $record !== null),
                    TextInput::make('name_translations.en')
                        ->label(__('Name (EN)'))
                        ->maxLength(255)
                        ->disabled(fn (?TaskCollection $record) => $record?->tenant_id !== $tenantId && $record !== null),
                    Select::make('event_type_id')
                        ->label(__('Event Type'))
                        ->options(fn () => EventType::orderBy('name->' . app()->getLocale())
                            ->get()
                            ->mapWithKeys(function (EventType $type) {
                                $name = $type->name[app()->getLocale()] ?? $type->name['de'] ?? reset($type->name);

                                return [$type->id => $name];
                            })->toArray())
                        ->searchable()
                        ->required()
                        ->disabled(fn (?TaskCollection $record) => $record?->tenant_id !== $tenantId && $record !== null),
                    Textarea::make('description_translations.de')
                        ->label(__('Description (DE)'))
                        ->rows(3)
                        ->disabled(fn (?TaskCollection $record) => $record?->tenant_id !== $tenantId && $record !== null),
                    Textarea::make('description_translations.en')
                        ->label(__('Description (EN)'))
                        ->rows(3)
                        ->disabled(fn (?TaskCollection $record) => $record?->tenant_id !== $tenantId && $record !== null),
                ])->columns(2),
        ]);
    }

    public static function table(Table $table): Table
    {
        return $table
            ->columns([
                TextColumn::make('name')
                    ->label(__('Name'))
                    ->searchable(['name_translations->de', 'name_translations->en'])
                    ->sortable(),
                BadgeColumn::make('eventType.name')
                    ->label(__('Event Type'))
                    ->color('info'),
                IconColumn::make('tenant_id')
                    ->label(__('Scope'))
                    ->boolean()
                    ->trueIcon('heroicon-o-user-group')
                    ->falseIcon('heroicon-o-globe-alt')
                    ->state(fn (TaskCollection $record) => $record->tenant_id !== null)
                    ->tooltip(fn (TaskCollection $record) => $record->tenant_id ? __('Tenant-only') : __('Global template')),
                TextColumn::make('tasks_count')
                    ->label(__('Tasks'))
                    ->counts('tasks')
                    ->sortable(),
            ])
            ->filters([
                SelectFilter::make('event_type_id')
                    ->label(__('Event Type'))
                    ->relationship('eventType', 'name->' . app()->getLocale()),
                SelectFilter::make('scope')
                    ->options([
                        'global' => __('Global template'),
                        'tenant' => __('Tenant-owned'),
                    ])
                    ->query(function ($query, $value) {
                        $tenantId = auth()->user()?->tenant_id;

                        if ($value === 'global') {
                            $query->whereNull('tenant_id');
                        }

                        if ($value === 'tenant') {
                            $query->where('tenant_id', $tenantId);
                        }
                    }),
            ])
            ->actions([
                \Filament\Actions\Action::make('import')
                    ->label(__('Import to Event'))
                    ->icon('heroicon-o-cloud-arrow-down')
                    ->form([
                        Select::make('event_slug')
                            ->label(__('Select Event'))
                            ->options(function () {
                                $tenantId = auth()->user()?->tenant_id;

                               return Event::where('tenant_id', $tenantId)
                                   ->orderBy('date', 'desc')
                                   ->get()
                                   ->mapWithKeys(function (Event $event) {
                                       $name = $event->name[app()->getLocale()] ?? $event->name['de'] ?? reset($event->name);

                                       return [
                                            $event->slug => sprintf('%s (%s)', $name, $event->date?->format('d.m.Y')),
                                        ];
                                    })->toArray();
                            })
                            ->required()
                            ->searchable(),
                    ])
                    ->action(function (TaskCollection $record, array $data) {
                        $event = Event::where('slug', $data['event_slug'])
                            ->where('tenant_id', auth()->user()?->tenant_id)
                            ->firstOrFail();

                        /** @var TaskCollectionImportService $service */
                        $service = app(TaskCollectionImportService::class);
                        $service->import($record, $event);

                        Notification::make()
                            ->title(__('Task collection imported'))
                            ->body(__('The collection :name has been imported.', ['name' => $record->name]))
                            ->success()
                            ->send();
                    }),
                Actions\EditAction::make()
                    ->label(__('Edit'))
                    ->visible(fn (TaskCollection $record) => $record->tenant_id === auth()->user()?->tenant_id),
            ])
            ->headerActions([
                Actions\CreateAction::make()
                    ->label(__('Create Task Collection'))
                    ->mutateFormDataUsing(function (array $data) {
                        $tenantId = auth()->user()?->tenant_id;

                        $data['tenant_id'] = $tenantId;
                        $data['slug'] = static::generateSlug($data['name_translations']['en'] ?? $data['name_translations']['de'] ?? 'collection', $tenantId);

                        return $data;
                    }),
            ])
            ->bulkActions([
                Actions\DeleteBulkAction::make()
                    ->visible(fn () => false),
            ]);
    }

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

    public static function getEloquentQuery(): Builder
    {
        $tenantId = auth()->user()?->tenant_id;

        return parent::getEloquentQuery()
            ->forTenant($tenantId)
            ->with('eventType')
            ->withCount('tasks');
    }

    public static function getGloballySearchableAttributes(): array
    {
        return ['name_translations->de', 'name_translations->en'];
    }

    public static function generateSlug(string $base, int $tenantId): string
    {
        $slugBase = Str::slug($base) ?: 'collection';

        do {
            $candidate = $slugBase . '-' . $tenantId . '-' . Str::random(4);
        } while (TaskCollection::where('slug', $candidate)->exists());

        return $candidate;
    }

    public static function scopeEloquentQueryToTenant(Builder $query, ?Model $tenant): Builder
    {
        $tenant ??= Filament::getTenant();

        if (! $tenant) {
            return $query;
        }

        return $query->where(function (Builder $innerQuery) use ($tenant) {
            $innerQuery->whereNull('tenant_id')
                ->orWhere('tenant_id', $tenant->getKey());
        });
    }
}
