<?php

declare(strict_types=1);

namespace App\Models;

use Illuminate\Support\Facades\Cache;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;

class WorldWebStory extends Model
{
    use HasFactory;
    use SoftDeletes;

    public const STATUS_DRAFT = 'draft';
    public const STATUS_PUBLISHED = 'published';
    public const STATUS_ARCHIVED = 'archived';

    protected $fillable = [
        'world_id',
        'slug',
        'title',
        'subtitle',
        'excerpt',
        'description',
        'seo_title',
        'seo_description',
        'poster_portrait_path',
        'poster_square_path',
        'publisher_logo_path',
        'status',
        'featured',
        'active',
        'noindex',
        'published_at',
        'starts_at',
        'ends_at',
        'created_by',
        'updated_by',
    ];

    protected $casts = [
        'featured' => 'boolean',
        'active' => 'boolean',
        'noindex' => 'boolean',
        'published_at' => 'datetime',
        'starts_at' => 'datetime',
        'ends_at' => 'datetime',
    ];

    protected static function booted(): void
    {
        $flushCache = static function (self $story): void {
            Cache::forget('web_story_index');
            Cache::forget('web_story:' . $story->slug);

            if ($story->world?->slug) {
                Cache::forget('world:' . $story->world->slug . ':web_story');
            } elseif ($story->world_id) {
                $worldSlug = World::query()->whereKey($story->world_id)->value('slug');
                if (is_string($worldSlug) && $worldSlug !== '') {
                    Cache::forget('world:' . $worldSlug . ':web_story');
                }
            }
        };

        static::saved($flushCache);
        static::deleted($flushCache);
        static::restored($flushCache);
    }

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

    public function pages(): HasMany
    {
        return $this->hasMany(WorldWebStoryPage::class, 'story_id')->orderedPages();
    }

    public function orderedPages(): HasMany
    {
        return $this->hasMany(WorldWebStoryPage::class, 'story_id')->orderedPages();
    }

    public function creator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    public function updater(): BelongsTo
    {
        return $this->belongsTo(User::class, 'updated_by');
    }

    public function scopePublished(Builder $query): Builder
    {
        return $query->where('status', self::STATUS_PUBLISHED);
    }

    public function scopeActive(Builder $query): Builder
    {
        return $query->where('active', true);
    }

    public function scopeFeatured(Builder $query): Builder
    {
        return $query->where('featured', true);
    }

    public function scopeVisible(Builder $query): Builder
    {
        return $query
            ->active()
            ->published()
            ->where('noindex', false)
            ->where(function (Builder $builder): void {
                $builder->whereNull('published_at')
                    ->orWhere('published_at', '<=', now());
            })
            ->where(function (Builder $builder): void {
                $builder->whereNull('starts_at')
                    ->orWhere('starts_at', '<=', now());
            })
            ->where(function (Builder $builder): void {
                $builder->whereNull('ends_at')
                    ->orWhere('ends_at', '>=', now());
            });
    }

    public function publicUrl(): string
    {
        return route('web-stories.show', ['slug' => $this->slug]);
    }

    public function posterPortraitUrl(): ?string
    {
        return $this->assetUrl($this->poster_portrait_path);
    }

    public function posterSquareUrl(): ?string
    {
        return $this->assetUrl($this->poster_square_path);
    }

    public function publisherLogoUrl(): ?string
    {
        return $this->assetUrl($this->publisher_logo_path);
    }

    public function seoTitle(): string
    {
        return trim((string) ($this->seo_title ?: $this->title));
    }

    public function seoDescription(): string
    {
        return trim((string) ($this->seo_description ?: $this->excerpt ?: $this->description ?: ''));
    }

    private function assetUrl(?string $path): ?string
    {
        $resolved = trim((string) $path);

        if ($resolved === '') {
            return null;
        }

        if (str_starts_with($resolved, 'http://') || str_starts_with($resolved, 'https://')) {
            return $resolved;
        }

        return rtrim((string) config('cdn.files_url', 'https://files.skinbase.org'), '/') . '/' . ltrim($resolved, '/');
    }
}