<?php

namespace App\Services\Storage;

use App\Models\Event;
use App\Models\EventMediaAsset;
use App\Models\EventStorageAssignment;
use App\Models\MediaStorageTarget;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;

class EventStorageManager
{
    public function getHotDiskForEvent(Event $event): string
    {
        $target = $event->currentStorageTarget('hot') ?? $this->resolveDefaultHotTarget();

        return $target?->key ?? Config::get('filesystems.default', 'local');
    }

    public function getArchiveDiskForEvent(Event $event): ?string
    {
        $assignment = $event->storageAssignments()
            ->where('role', 'archive')
            ->where('status', 'active')
            ->latest('assigned_at')
            ->first();

        if ($assignment?->storageTarget) {
            return $assignment->storageTarget->key;
        }

        $default = $this->resolveDefaultArchiveTarget();

        if (! $default) {
            return null;
        }

        $assignment = $this->ensureAssignment($event, $default, 'archive');

        return $assignment->storageTarget?->key;
    }

    public function ensureAssignment(Event $event, ?MediaStorageTarget $target = null, string $role = 'hot'): EventStorageAssignment
    {
        if (! $target) {
            $target = $role === 'archive'
                ? $this->resolveDefaultArchiveTarget()
                : $this->resolveDefaultHotTarget();
        }

        $assignment = $event->storageAssignments()
            ->where('role', $role)
            ->where('status', 'active')
            ->where('media_storage_target_id', $target?->id)
            ->latest('assigned_at')
            ->first();

        if ($assignment) {
            return $assignment;
        }

        if (! $target) {
            throw new \RuntimeException('No storage target available for role '.$role);
        }

        $assignment = $event->storageAssignments()->create([
            'media_storage_target_id' => $target->id,
            'role' => $role,
            'status' => 'active',
            'assigned_at' => now(),
        ]);

        return $assignment;
    }

    public function recordAsset(
        Event $event,
        string $disk,
        string $path,
        array $attributes = [],
        ?EventMediaAsset $existing = null,
    ): EventMediaAsset {
        $target = MediaStorageTarget::where('key', $disk)->first();

        if (! $target) {
            $target = $this->resolveDefaultHotTarget();
        }

        $payload = array_merge([
            'event_id' => $event->id,
            'media_storage_target_id' => $target?->id,
            'disk' => $disk,
            'path' => $path,
            'status' => 'hot',
            'processed_at' => now(),
        ], $attributes);

        if ($existing) {
            $existing->fill($payload)->save();

            return $existing;
        }

        return EventMediaAsset::create($payload);
    }

    public function registerDynamicDisks(): void
    {
        if (! $this->targetsTableExists()) {
            return;
        }

        $targets = MediaStorageTarget::active()->get();

        foreach ($targets as $target) {
            $config = $target->toFilesystemConfig();
            Config::set('filesystems.disks.'.$target->key, $config);
        }
    }

    protected function resolveDefaultHotTarget(): ?MediaStorageTarget
    {
        return MediaStorageTarget::active()
            ->where('is_hot', true)
            ->orderByDesc('is_default')
            ->orderByDesc('priority')
            ->first();
    }

    protected function resolveDefaultArchiveTarget(): ?MediaStorageTarget
    {
        return MediaStorageTarget::active()
            ->where('is_hot', false)
            ->orderByDesc('priority')
            ->first();
    }

    protected function targetsTableExists(): bool
    {
        static $cached;

        if ($cached !== null) {
            return $cached;
        }

        try {
            $cached = \Schema::hasTable('media_storage_targets');
        } catch (\Throwable $e) {
            Log::debug('Skipping storage target bootstrap: '.$e->getMessage());
            $cached = false;
        }

        return $cached;
    }
}
