<?php

namespace App\Models;

use App\Services\EventJoinTokenService;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;

class Event extends Model
{
    use HasFactory;

    protected $table = 'events';

    protected $guarded = [];

    protected $casts = [
        'date' => 'datetime',
        'is_active' => 'boolean',
        'name' => 'array',
        'description' => 'array',
        'live_show_token_rotated_at' => 'datetime',
    ];

    protected static function booted(): void
    {
        static::created(function (self $event): void {
            if ($event->joinTokens()->exists()) {
                return;
            }

            app(EventJoinTokenService::class)->createToken($event, [
                'label' => 'Standard-Link',
                'metadata' => [
                    'auto_generated' => true,
                ],
            ]);
        });
    }

    public function storageAssignments(): HasMany
    {
        return $this->hasMany(EventStorageAssignment::class);
    }

    public function mediaAssets(): HasMany
    {
        return $this->hasMany(EventMediaAsset::class);
    }

    public function currentStorageTarget(?string $role = 'hot'): ?MediaStorageTarget
    {
        $assignment = $this->storageAssignments()
            ->where('role', $role)
            ->where('status', 'active')
            ->latest('assigned_at')
            ->first();

        return $assignment?->storageTarget;
    }

    public function tenant(): BelongsTo
    {
        return $this->belongsTo(Tenant::class);
    }

    public function eventType(): BelongsTo
    {
        return $this->belongsTo(EventType::class);
    }

    public function photos(): HasMany
    {
        return $this->hasMany(Photo::class);
    }

    public function taskCollections(): BelongsToMany
    {
        return $this->belongsToMany(
            TaskCollection::class,
            'event_task_collection',
            'event_id',
            'task_collection_id'
        );
    }

    public function tasks(): BelongsToMany
    {
        return $this->belongsToMany(Task::class, 'event_task', 'event_id', 'task_id')
            ->withPivot(['sort_order'])
            ->withTimestamps();
    }

    public function eventPackage(): BelongsTo
    {
        return $this->belongsTo(EventPackage::class);
    }

    public function eventPackages(): HasMany
    {
        return $this->hasMany(EventPackage::class);
    }

    public function retentionOverrides(): HasMany
    {
        return $this->hasMany(RetentionOverride::class);
    }

    public function joinTokens(): HasMany
    {
        return $this->hasMany(EventJoinToken::class);
    }

    public function members(): HasMany
    {
        return $this->hasMany(EventMember::class);
    }

    public function photoboothSetting(): HasOne
    {
        return $this->hasOne(EventPhotoboothSetting::class);
    }

    public function guestNotifications(): HasMany
    {
        return $this->hasMany(GuestNotification::class);
    }

    public function hasActivePackage(): bool
    {
        return $this->eventPackage && $this->eventPackage->isActive();
    }

    public function getPackageLimits(): array
    {
        if (! $this->hasActivePackage()) {
            return [];
        }

        return $this->eventPackage->package->limits;
    }

    public function canUploadPhoto(): bool
    {
        if (! $this->hasActivePackage()) {
            return false;
        }

        return $this->eventPackage->canUploadPhoto();
    }

    public function ensureLiveShowToken(): string
    {
        if (is_string($this->live_show_token) && $this->live_show_token !== '') {
            return $this->live_show_token;
        }

        return $this->rotateLiveShowToken();
    }

    public function rotateLiveShowToken(): string
    {
        do {
            $token = bin2hex(random_bytes(32));
        } while (self::query()->where('live_show_token', $token)->exists());

        $this->forceFill([
            'live_show_token' => $token,
            'live_show_token_rotated_at' => now(),
        ])->save();

        return $token;
    }

    public function getSettingsAttribute($value): array
    {
        if (is_array($value)) {
            return $value;
        }

        if (is_string($value) && $value !== '') {
            $decoded = json_decode($value, true);

            return is_array($decoded) ? $decoded : [];
        }

        return [];
    }

    public function setSettingsAttribute($value): void
    {
        if (is_string($value)) {
            $decoded = json_decode($value, true);
            $value = is_array($decoded) ? $decoded : [];
        }

        $this->attributes['settings'] = json_encode($value ?? []);
    }
}
