<?php

namespace FluxCms\Core\Models;

use Illuminate\Database\Eloquent\Model;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\Tags\HasTags;
use Spatie\Translatable\HasTranslations;

class BlogPost extends Model implements HasMedia
{
    use HasTags, HasTranslations, InteractsWithMedia;

    public function getTable()
    {
        return config('flux-cms.database.table_prefix', 'flux_cms_').'blog_posts';
    }

    protected $fillable = [
        'domain_key',
        'title',
        'excerpt',
        'content',
        'meta_title',
        'meta_description',
        'is_published',
        'is_featured',
        'published_at',
        'author_id',
        'category',
        'settings',
    ];

    protected $translatable = [
        'title',
        'excerpt',
        'content',
        'meta_title',
        'meta_description',
    ];

    protected $casts = [
        'title' => 'array',
        'excerpt' => 'array',
        'content' => 'array',
        'meta_title' => 'array',
        'meta_description' => 'array',
        'settings' => 'array',
        'is_published' => 'boolean',
        'is_featured' => 'boolean',
        'published_at' => 'datetime',
    ];

    public function author()
    {
        return $this->morphTo();
    }

    /**
     * Slug relationship
     */
    public function slugs()
    {
        return $this->morphMany(Slug::class, 'model');
    }

    /**
     * Scopes
     */
    public function scopeForDomain($query, string $domainKey)
    {
        return $query->where('domain_key', $domainKey);
    }

    public function scopePublished($query)
    {
        return $query->where('is_published', true)
            ->where('published_at', '<=', now());
    }

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

    public function scopeByCategory($query, string $category)
    {
        return $query->where('category', $category);
    }

    public function scopeByTag($query, string $tag)
    {
        return $query->withAnyTags([$tag]);
    }

    public function scopeRecent($query, int $limit = 10)
    {
        return $query->orderBy('published_at', 'desc')->limit($limit);
    }

    public function scopeBySlug($query, string $slug, ?string $locale = null)
    {
        $locale = $locale ?? app()->getLocale();

        return $query->whereHas('slugs', function ($q) use ($slug, $locale) {
            $q->where('slug', $slug)->where('locale', $locale);
        });
    }

    public function scopeBySlugWithFallback($query, string $slug, ?string $locale = null)
    {
        $locale = $locale ?? app()->getLocale();
        $fallbackLocale = config('app.fallback_locale');

        return $query->where(function ($q) use ($slug, $locale, $fallbackLocale) {
            $q->whereHas('slugs', function ($sq) use ($slug, $locale) {
                $sq->where('slug', $slug)->where('locale', $locale);
            })->orWhereHas('slugs', function ($sq) use ($slug, $fallbackLocale) {
                $sq->where('slug', $slug)->where('locale', $fallbackLocale);
            });
        });
    }

    /**
     * Get the URL for this blog post
     */
    public function getUrl(?string $locale = null): string
    {
        $locale = $locale ?? app()->getLocale();
        $slug = $this->slugs()->where('locale', $locale)->first();

        return route('blog.post', ['slug' => $slug->slug ?? '']);
    }

    /**
     * Get the reading time estimate in minutes
     */
    public function getReadingTimeAttribute(): int
    {
        $content = strip_tags($this->getTranslation('content', app()->getLocale()));
        $wordCount = str_word_count($content);

        return max(1, ceil($wordCount / 200)); // Assuming 200 words per minute
    }

    /**
     * Get excerpt with fallback to content
     */
    public function getExcerptAttribute($value): string
    {
        $locale = app()->getLocale();
        $excerpt = $this->getTranslation('excerpt', $locale);

        if (empty($excerpt)) {
            $content = strip_tags($this->getTranslation('content', $locale));
            $excerpt = str_limit($content, 160);
        }

        return $excerpt;
    }

    /**
     * Check if post is published
     */
    public function isPublished(): bool
    {
        return $this->is_published &&
            $this->published_at &&
            $this->published_at <= now();
    }

    /**
     * Get SEO title with fallback to title
     */
    public function getSeoTitle(?string $locale = null): string
    {
        $locale = $locale ?? app()->getLocale();

        return $this->getTranslation('meta_title', $locale)
            ?? $this->getTranslation('title', $locale);
    }

    /**
     * Get SEO description with fallback to excerpt
     */
    public function getSeoDescription(?string $locale = null): string
    {
        $locale = $locale ?? app()->getLocale();

        return $this->getTranslation('meta_description', $locale)
            ?? $this->getTranslation('excerpt', $locale);
    }

    /**
     * Media collections
     */
    public function registerMediaCollections(): void
    {
        $this->addMediaCollection('featured_image')
            ->singleFile()
            ->acceptsMimeTypes(['image/jpeg', 'image/png', 'image/webp']);

        $this->addMediaCollection('gallery')
            ->acceptsMimeTypes(['image/jpeg', 'image/png', 'image/webp']);
    }

    public function registerMediaConversions(?Media $media = null): void
    {
        $this->addMediaConversion('thumb')
            ->width(300)
            ->height(200)
            ->sharpen(10);

        $this->addMediaConversion('hero')
            ->width(1200)
            ->height(600)
            ->optimize();
    }

    /**
     * Get featured image
     */
    public function getFeaturedImage(): ?Media
    {
        return $this->getFirstMedia('featured_image');
    }

    /**
     * Get featured image URL
     */
    public function getFeaturedImageUrl(string $conversion = ''): ?string
    {
        $media = $this->getFeaturedImage();

        if (! $media) {
            return null;
        }

        return $conversion ? $media->getUrl($conversion) : $media->getUrl();
    }

    /**
     * Settings management
     */
    public function getSetting(string $key, mixed $default = null): mixed
    {
        return data_get($this->settings, $key, $default);
    }

    public function setSetting(string $key, mixed $value): void
    {
        $settings = $this->settings ?? [];
        data_set($settings, $key, $value);
        $this->update(['settings' => $settings]);
    }
}
