<?php

namespace Database\Seeders;

use App\Models\Emotion;
use App\Models\Event;
use App\Models\Photo;
use App\Models\PhotoLike;
use App\Models\Task;
use App\Models\Tenant;
use Carbon\CarbonImmutable;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class DemoAchievementsSeeder extends Seeder
{
    public function run(): void
    {
        $tenant = Tenant::where('slug', 'demo-tenant')->first();

        if (! $tenant) {
            $this->command?->warn('Demo tenant missing – skipping DemoAchievementsSeeder');

            return;
        }

        $sourceFiles = collect(Storage::disk('public')->files('photos'))
            ->filter(fn ($path) => Str::endsWith(Str::lower($path), '.jpg'))
            ->values();

        if ($sourceFiles->isEmpty()) {
            $this->command?->warn('No demo photo files found – skipping DemoAchievementsSeeder');

            return;
        }

        $emotions = Emotion::pluck('id')->all();
        if ($emotions === []) {
            $this->command?->warn('No emotions available – skipping DemoAchievementsSeeder');

            return;
        }

        $scenarios = [
            [
                'event' => Event::with(['tasks', 'eventType'])
                    ->where('slug', 'demo-wedding-2025')
                    ->first(),
                'blueprints' => [
                    ['guest' => 'Anna Mueller', 'photos' => 6, 'likes' => [12, 8, 5, 4, 2, 1], 'withTasks' => true],
                    ['guest' => 'Max Schmidt', 'photos' => 4, 'likes' => [9, 7, 4, 2], 'withTasks' => true],
                    ['guest' => 'Lisa Weber', 'photos' => 2, 'likes' => [3, 1], 'withTasks' => false],
                    ['guest' => 'Tom Fischer', 'photos' => 1, 'likes' => [14], 'withTasks' => true],
                    ['guest' => 'Team Brautparty', 'photos' => 5, 'likes' => [5, 4, 3, 3, 2], 'withTasks' => true],
                ],
            ],
            [
                'event' => Event::with(['tasks', 'eventType'])
                    ->where('slug', 'demo-corporate-2025')
                    ->first(),
                'blueprints' => [
                    ['guest' => 'HR Dream Team', 'photos' => 4, 'likes' => [8, 6, 4, 3], 'withTasks' => true],
                    ['guest' => 'Innovation Squad', 'photos' => 5, 'likes' => [10, 7, 5, 4, 2], 'withTasks' => true],
                    ['guest' => 'Finance Crew', 'photos' => 3, 'likes' => [6, 5, 2], 'withTasks' => false],
                    ['guest' => 'New Joiners', 'photos' => 4, 'likes' => [5, 4, 3, 2], 'withTasks' => true],
                ],
            ],
        ];

        foreach ($scenarios as $scenario) {
            /** @var Event|null $event */
            $event = $scenario['event'];

            if (! $event) {
                $this->command?->warn('Demo event missing – skipping achievements for one scenario.');

                continue;
            }

            $taskIds = $event->tasks()->pluck('tasks.id')->all();
            if ($taskIds === []) {
                $taskIds = Task::where('event_type_id', $event->event_type_id ?? optional($event->eventType)->id)
                    ->pluck('id')
                    ->all();
            }

            if ($taskIds === []) {
                $this->command?->warn(sprintf('No tasks available for %s – achievements will use taskless entries.', $event->slug));
            }

            $eventDate = $event->date ? CarbonImmutable::parse($event->date) : CarbonImmutable::now();
            $baseDir = "events/{$event->id}/achievements";

            Storage::disk('public')->makeDirectory($baseDir);
            Storage::disk('public')->makeDirectory("{$baseDir}/thumbs");

            $photoIndex = 0;

            foreach ($scenario['blueprints'] as $groupIndex => $blueprint) {
                for ($i = 0; $i < $blueprint['photos']; $i++) {
                    $sourcePath = $sourceFiles[$photoIndex % $sourceFiles->count()];
                    $photoIndex++;

                    $filename = Str::slug($blueprint['guest'].'-'.$groupIndex.'-'.$i).'.jpg';
                    $destPath = "{$baseDir}/{$filename}";

                    if (! Storage::disk('public')->exists($destPath)) {
                        Storage::disk('public')->copy($sourcePath, $destPath);
                    }

                    $thumbSource = str_replace('photos/', 'thumbnails/', $sourcePath);
                    $thumbDest = "{$baseDir}/thumbs/{$filename}";

                    if (Storage::disk('public')->exists($thumbSource)) {
                        Storage::disk('public')->copy($thumbSource, $thumbDest);
                    } else {
                        Storage::disk('public')->copy($sourcePath, $thumbDest);
                    }

                    $taskId = null;
                    if (! empty($taskIds) && ($blueprint['withTasks'] ?? false)) {
                        $taskId = $taskIds[($groupIndex + $i) % count($taskIds)];
                    }

                    $emotionId = $emotions[($groupIndex * 3 + $i) % count($emotions)];
                    $createdAt = $eventDate->addHours($groupIndex * 2 + $i);
                    $likes = $blueprint['likes'][$i] ?? 0;

                    $photo = Photo::updateOrCreate(
                        [
                            'tenant_id' => $tenant->id,
                            'event_id' => $event->id,
                            'guest_name' => $blueprint['guest'],
                            'file_path' => $destPath,
                        ],
                        [
                            'task_id' => $taskId,
                            'emotion_id' => $emotionId,
                            'thumbnail_path' => $thumbDest,
                            'likes_count' => $likes,
                            'is_featured' => $i === 0,
                            'metadata' => ['demo' => true, 'achievement' => true],
                            'created_at' => $createdAt,
                            'updated_at' => $createdAt,
                        ]
                    );

                    PhotoLike::where('photo_id', $photo->id)->delete();
                    for ($like = 0; $like < min($likes, 15); $like++) {
                        PhotoLike::create([
                            'photo_id' => $photo->id,
                            'guest_name' => 'Guest_'.Str::random(6),
                            'ip_address' => '10.0.'.rand(0, 254).'.'.rand(0, 254),
                            'created_at' => $createdAt->addMinutes($like * 3),
                        ]);
                    }
                }
            }

            $this->command?->info(sprintf('Demo achievements seeded for %s.', $event->slug));
        }
    }
}
