<?php

namespace App\Filament\Tenant\Pages;

use App\Models\Event;
use App\Models\EventJoinToken;
use App\Services\EventJoinTokenService;
use App\Support\JoinTokenLayoutRegistry;
use App\Support\TenantOnboardingState;
use BackedEnum;
use Filament\Notifications\Notification;
use Filament\Pages\Page;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\URL;

class InviteStudio extends Page
{
    protected static BackedEnum|string|null $navigationIcon = 'heroicon-o-qr-code';

    protected string $view = 'filament.tenant.pages.invite-studio';

    protected static ?string $navigationLabel = 'Einladungen & QR';

    protected static ?string $slug = 'invite-studio';

    protected static ?string $title = 'Einladungen & QR-Codes';

    protected static ?int $navigationSort = 50;

    public ?int $selectedEventId = null;

    public string $tokenLabel = '';

    public array $tokens = [];

    public array $layouts = [];

    protected static bool $shouldRegisterNavigation = true;

    public function mount(): void
    {
        $tenant = TenantOnboardingState::tenant();

        abort_if(! $tenant, 403);

        if (! TenantOnboardingState::completed($tenant)) {
            $this->redirect(TenantOnboarding::getUrl());

            return;
        }

        $firstEventId = $tenant->events()->orderBy('date')->value('id');

        $this->selectedEventId = $firstEventId;
        $this->layouts = $this->buildLayouts();

        if ($this->selectedEventId) {
            $this->loadEventContext();
        }
    }

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

    public function updatedSelectedEventId(): void
    {
        $this->loadEventContext();
    }

    public function createInvite(EventJoinTokenService $service): void
    {
        $this->validate([
            'selectedEventId' => ['required', 'exists:events,id'],
            'tokenLabel' => ['nullable', 'string', 'max:120'],
        ]);

        $tenant = TenantOnboardingState::tenant();

        abort_if(! $tenant, 403);

        $event = $tenant->events()->whereKey($this->selectedEventId)->first();

        if (! $event) {
            Notification::make()
                ->title('Event konnte nicht gefunden werden')
                ->danger()
                ->send();

            return;
        }

        $label = $this->tokenLabel ?: 'Einladung '.now()->format('d.m.');

        $layoutPreference = Arr::get($tenant->settings ?? [], 'branding.preferred_invite_layout');

        $service->createToken($event, [
            'label' => $label,
            'metadata' => [
                'preferred_layout' => $layoutPreference,
            ],
            'created_by' => auth()->id(),
        ]);

        $this->tokenLabel = '';

        $this->loadEventContext();

        Notification::make()
            ->title('Neuer Einladungslink erstellt')
            ->success()
            ->send();
    }

    protected function loadEventContext(): void
    {
        $tenant = TenantOnboardingState::tenant();

        if (! $tenant || ! $this->selectedEventId) {
            $this->tokens = [];

            return;
        }

        $event = $tenant->events()->whereKey($this->selectedEventId)->first();

        if (! $event) {
            $this->tokens = [];

            return;
        }

        $this->tokens = $event->joinTokens()
            ->orderByDesc('created_at')
            ->get()
            ->map(fn (EventJoinToken $token) => $this->mapToken($event, $token))
            ->toArray();
    }

    protected function mapToken(Event $event, EventJoinToken $token): array
    {
        $downloadUrls = JoinTokenLayoutRegistry::toResponse(function (string $layoutId, string $format) use ($event, $token) {
            return route('api.v1.tenant.events.join-tokens.layouts.download', [
                'event' => $event->slug,
                'joinToken' => $token->getKey(),
                'layout' => $layoutId,
                'format' => $format,
            ]);
        });

        return [
            'id' => $token->getKey(),
            'label' => $token->label ?? 'Einladungslink',
            'url' => URL::to('/e/'.$token->token),
            'created_at' => optional($token->created_at)->format('d.m.Y H:i'),
            'usage_count' => $token->usage_count,
            'usage_limit' => $token->usage_limit,
            'active' => $token->isActive(),
            'downloads' => $downloadUrls,
        ];
    }

    protected function buildLayouts(): array
    {
        return collect(JoinTokenLayoutRegistry::all())
            ->map(fn (array $layout) => [
                'id' => $layout['id'],
                'name' => $layout['name'],
                'subtitle' => $layout['subtitle'] ?? '',
                'description' => $layout['description'] ?? '',
            ])
            ->toArray();
    }

    public function getEventsProperty(): Collection
    {
        $tenant = TenantOnboardingState::tenant();

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

        return $tenant->events()->orderBy('date')->get();
    }
}
