<?php

declare(strict_types=1);

namespace App\Models;

use App\Models\StoryLike;
use App\Models\StoryBookmark;
use App\Models\StoryComment;
use App\Models\StoryView;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;

/**
 * Creator Story model.
 *
 * @property int              $id
 * @property string           $slug
 * @property string           $title
 * @property string|null      $excerpt
 * @property string|null      $content
 * @property string|null      $cover_image
 * @property int|null         $creator_id
 * @property int              $views
 * @property bool             $featured
 * @property string           $status   draft|pending_review|published|scheduled|archived|rejected
 * @property \Carbon\Carbon|null $published_at
 * @property int|null         $legacy_interview_id
 */
class Story extends Model
{
    use HasFactory;

    protected $table = 'stories';

    protected $fillable = [
        'slug',
        'title',
        'excerpt',
        'content',
        'cover_image',
        'creator_id',
        'story_type',
        'reading_time',
        'views',
        'likes_count',
        'comments_count',
        'featured',
        'status',
        'published_at',
        'scheduled_for',
        'meta_title',
        'meta_description',
        'canonical_url',
        'og_image',
        'submitted_for_review_at',
        'reviewed_at',
        'reviewed_by_id',
        'rejected_reason',
        'legacy_interview_id',
    ];

    protected $casts = [
        'featured'     => 'boolean',
        'published_at' => 'datetime',
        'scheduled_for' => 'datetime',
        'submitted_for_review_at' => 'datetime',
        'reviewed_at' => 'datetime',
        'views'        => 'integer',
        'likes_count'  => 'integer',
        'comments_count' => 'integer',
        'reading_time' => 'integer',
    ];

    // ── Relations ────────────────────────────────────────────────────────

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

    // Legacy alias used by older views/controllers.
    public function author(): BelongsTo
    {
        return $this->creator();
    }

    public function tags(): BelongsToMany
    {
        return $this->belongsToMany(StoryTag::class, 'relation_story_tags', 'story_id', 'tag_id');
    }

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

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

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

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

    // ── Scopes ───────────────────────────────────────────────────────────

    public function scopePublished($query)
    {
        return $query
            ->where(function ($q): void {
                $q->where('status', 'published')
                    ->orWhere(function ($scheduled): void {
                        $scheduled->where('status', 'scheduled')
                            ->whereNotNull('published_at')
                            ->where('published_at', '<=', now());
                    });
            })
            ->where(fn ($q) => $q->whereNull('published_at')->orWhere('published_at', '<=', now()));
    }

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

    // ── Accessors ────────────────────────────────────────────────────────

    public function getUrlAttribute(): string
    {
        return url('/stories/' . $this->slug);
    }

    public function getCoverUrlAttribute(): ?string
    {
        return $this->resolveStoryMediaUrl($this->cover_image);
    }

    public function getOgImageUrlAttribute(): ?string
    {
        return $this->resolveStoryMediaUrl($this->og_image);
    }

    /**
     * Estimated reading time in minutes based on word count.
     */
    public function getReadingTimeAttribute(): int
    {
        if (! empty($this->attributes['reading_time'])) {
            return max(1, (int) $this->attributes['reading_time']);
        }

        $wordCount = str_word_count(strip_tags((string) $this->content));

        return max(1, (int) ceil($wordCount / 200));
    }

    /**
     * Short excerpt for meta descriptions / cards.
     * Strips HTML, truncates to ~160 characters.
     */
    public function getMetaExcerptAttribute(): string
    {
        $text = $this->excerpt ?: strip_tags((string) $this->content);

        return \Illuminate\Support\Str::limit($text, 160);
    }

    private function resolveStoryMediaUrl(?string $value): ?string
    {
        if (! $value) {
            return null;
        }

        if (str_starts_with($value, 'http')) {
            return $value;
        }

        $path = ltrim($value, '/');
        if (str_starts_with($path, 'storage/')) {
            $path = substr($path, strlen('storage/'));
        }

        if (preg_match('#^stories/(sm|md|original)/[a-f0-9]{2}/[a-f0-9]{2}/[a-f0-9]+\.(webp|jpg|jpeg|png)$#', $path) === 1) {
            $cdnBase = rtrim((string) config('cdn.files_url', ''), '/');

            return $cdnBase !== ''
                ? $cdnBase . '/' . $path
                : Storage::disk('public')->url($path);
        }

        return asset($value);
    }
}
