<?php

namespace Database\Seeders;

use App\Models\Event;
use App\Models\EventPackage;
use App\Models\EventType;
use App\Models\Package;
use App\Models\PackagePurchase;
use App\Models\Task;
use App\Models\TaskCollection;
use App\Models\Tenant;
use App\Services\EventJoinTokenService;
use Illuminate\Database\Seeder;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Schema;

class DemoEventSeeder extends Seeder
{
    public function run(): void
    {
        $demoTenant = Tenant::where('slug', 'demo-tenant')->first();
        if (! $demoTenant) {
            return;
        }

        $weddingType = EventType::where('slug', 'wedding')->first();
        $corporateType = EventType::where('slug', 'corporate')->first();

        $standardPackage = Package::where('slug', 'standard')->first()
            ?? Package::where('type', 'endcustomer')->orderBy('price')->first();
        $premiumPackage = Package::where('slug', 'premium')->first()
            ?? Package::where('type', 'endcustomer')->orderByDesc('price')->first();

        $events = [
            [
                'slug' => 'demo-wedding-2025',
                'name' => ['de' => 'Demo Hochzeit 2025', 'en' => 'Demo Wedding 2025'],
                'description' => ['de' => 'Demo-Event', 'en' => 'Demo event'],
                'date' => Carbon::now()->addMonths(3),
                'event_type' => $weddingType,
                'package' => $standardPackage,
                'token_label' => 'Demo QR',
                'token_value' => 'W2E3sbt7yclzpkAwNSARHYTVN1sPLBad8hfUjLVHmjkUviPd',
                'collection_slugs' => ['wedding-classics-2025'],
                'task_slug_prefix' => 'wedding-',
                'branding' => [
                    'primary_color' => '#FF5A5F',
                    'secondary_color' => '#FFF8F5',
                    'background_color' => '#FFF8F5',
                    'font_family' => 'Playfair Display, serif',
                ],
            ],
            [
                'slug' => 'demo-corporate-2025',
                'name' => ['de' => 'Demo Firmen-Event 2025', 'en' => 'Demo Corporate Summit 2025'],
                'description' => ['de' => 'Launch-Event mit Networking', 'en' => 'Launch event with networking sessions'],
                'date' => Carbon::now()->addMonths(2),
                'event_type' => $corporateType,
                'package' => $premiumPackage,
                'token_label' => 'Corporate QR',
                'collection_slugs' => ['corporate-classics-2025'],
                'task_slug_prefix' => 'corporate-',
                'branding' => [
                    'primary_color' => '#0ea5e9',
                    'secondary_color' => '#2563eb',
                    'background_color' => '#0f172a',
                    'font_family' => 'Inter, sans-serif',
                ],
            ],
        ];

        foreach ($events as $config) {
            if (! $config['event_type'] || ! $config['package']) {
                continue;
            }

            $event = Event::updateOrCreate(
                ['slug' => $config['slug']],
                [
                    'tenant_id' => $demoTenant->id,
                    'name' => $config['name'],
                    'description' => $config['description'],
                    'date' => $config['date']->toDateString(),
                    'event_type_id' => $config['event_type']->id,
                    'status' => 'published',
                    'is_active' => true,
                    'settings' => [
                        'branding' => $config['branding'],
                    ],
                    'default_locale' => 'de',
                ]
            );

            $this->ensureJoinToken($event, $config['token_label'], $config['token_value'] ?? null);

            $this->attachEventPackage(
                event: $event,
                package: $config['package'],
                tenant: $demoTenant,
                providerId: 'demo-seed-'.$config['slug'],
                purchasedAt: Carbon::now()->subDays(7)
            );

            $this->attachTaskCollections($event, $config['collection_slugs']);
            $this->attachEventTasks($event, $config['task_slug_prefix']);
        }
    }

    private function ensureJoinToken(Event $event, string $label, ?string $token = null): void
    {
        if ($event->joinTokens()->exists()) {
            $existingToken = $event->joinTokens()->latest('id')->first();
            if ($existingToken) {
                $metadata = $existingToken->metadata ?? [];
                if (! array_key_exists('demo_read_only', $metadata)) {
                    $metadata['demo_read_only'] = true;
                    $existingToken->metadata = $metadata;
                    $existingToken->save();
                }
            }

            return;
        }

        $metadata = ['demo_read_only' => true];

        if ($token) {
            $metadata = array_merge($metadata, ['seeded' => true, 'plain_token' => $token]);
        }

        $attributes = [
            'label' => $label,
            'metadata' => $metadata,
        ];

        $tokenModel = app(EventJoinTokenService::class)->createToken($event, $attributes);

        if ($token) {
            $hash = hash('sha256', $token);
            $preview = strlen($token) <= 10 ? $token : substr($token, 0, 6).'…'.substr($token, -4);

            $tokenModel->forceFill([
                'token' => $hash,
                'token_hash' => $hash,
                'token_encrypted' => Crypt::encryptString($token),
                'token_preview' => $preview,
            ])->save();
        }
    }

    private function attachEventPackage(Event $event, Package $package, Tenant $tenant, string $providerId, Carbon $purchasedAt): void
    {
        $eventPackageData = [
            'purchased_price' => $package->price,
            'purchased_at' => $purchasedAt,
        ];

        if (Schema::hasColumn('event_packages', 'used_photos')) {
            $eventPackageData['used_photos'] = 0;
        }

        if (Schema::hasColumn('event_packages', 'used_guests')) {
            $eventPackageData['used_guests'] = 0;
        }

        if (Schema::hasColumn('event_packages', 'gallery_expires_at')) {
            $eventPackageData['gallery_expires_at'] = $purchasedAt->copy()->addDays($package->gallery_days ?? 30);
        }

        EventPackage::updateOrCreate(
            [
                'event_id' => $event->id,
                'package_id' => $package->id,
            ],
            $eventPackageData
        );

        PackagePurchase::updateOrCreate(
            [
                'tenant_id' => $tenant->id,
                'package_id' => $package->id,
                'provider_id' => $providerId,
            ],
            [
                'event_id' => $event->id,
                'price' => $package->price,
                'type' => $package->type === 'reseller' ? 'reseller_subscription' : 'endcustomer_event',
                'purchased_at' => $purchasedAt,
                'metadata' => ['demo' => true, 'event_slug' => $event->slug],
                'ip_address' => null,
                'user_agent' => null,
            ]
        );
    }

    private function attachTaskCollections(Event $event, array $collectionSlugs): void
    {
        if ($collectionSlugs === []) {
            return;
        }

        $collections = TaskCollection::whereIn('slug', $collectionSlugs)->get();

        $pivot = [];
        foreach ($collections as $index => $collection) {
            $pivot[$collection->id] = ['sort_order' => ($index + 1) * 10];
        }

        if ($pivot !== []) {
            $event->taskCollections()->syncWithoutDetaching($pivot);
        }
    }

    private function attachEventTasks(Event $event, string $slugPrefix): void
    {
        $tasks = [];

        if ($event->event_type_id) {
            $tasks = Task::where('event_type_id', $event->event_type_id)
                ->orderBy('sort_order')
                ->limit(25)
                ->pluck('id')
                ->all();
        }

        if ($tasks === [] && $slugPrefix !== '') {
            $tasks = Task::where('slug', 'like', $slugPrefix.'%')
                ->orderBy('sort_order')
                ->limit(25)
                ->pluck('id')
                ->all();
        }

        if ($tasks === []) {
            $tasks = Task::where('tenant_id', $event->tenant_id)
                ->orderBy('sort_order')
                ->limit(20)
                ->pluck('id')
                ->all();
        }

        if ($tasks === []) {
            return;
        }

        $tasks = array_slice(array_unique($tasks), 0, 20);

        $pivot = [];
        foreach ($tasks as $index => $taskId) {
            $pivot[$taskId] = ['sort_order' => ($index + 1) * 10];
        }

        $event->tasks()->syncWithoutDetaching($pivot);
    }
}
