<?php

namespace App\Models;

use App\Enums\FeedColorEnum;
use Database\Factories\FeedFactory;
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\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Carbon;

/**
 * @property int $id
 * @property string $name
 * @property string $url
 * @property string $type
 * @property string $provider
 * @property int|null $language_id
 * @property Language|null $language
 * @property string|null $description
 * @property FeedColorEnum|null $color
 * @property array<string, mixed> $settings
 * @property bool $is_active
 * @property Carbon|null $last_fetched_at
 * @property Carbon $created_at
 * @property Carbon $updated_at
 *
 * @method static orderBy(string $string, string $string1)
 * @method static where(string $string, true $true)
 * @method static findOrFail(mixed $feed_id)
 */
class Feed extends Model
{
    /** @use HasFactory<FeedFactory> */
    use HasFactory;

    private const RECENT_FETCH_THRESHOLD_HOURS = 2;

    private const DAILY_FETCH_THRESHOLD_HOURS = 24;

    protected $fillable = [
        'name',
        'url',
        'type',
        'provider',
        'language_id',
        'description',
        'color',
        'settings',
        'is_active',
        'last_fetched_at',
    ];

    protected $casts = [
        'settings' => 'array',
        'is_active' => 'boolean',
        'last_fetched_at' => 'datetime',
        'color' => FeedColorEnum::class,
    ];

    public function displayColor(): FeedColorEnum
    {
        return $this->color ?? FeedColorEnum::forId($this->id);
    }

    public function getTypeDisplayAttribute(): string
    {
        return match ($this->type) {
            'website' => 'Website',
            'rss' => 'RSS Feed',
            default => 'Unknown'
        };
    }

    public function getStatusAttribute(): string
    {
        if (! $this->is_active) {
            return 'Inactive';
        }

        if (! $this->last_fetched_at) {
            return 'Never fetched';
        }

        $hoursAgo = $this->last_fetched_at->diffInHours(now());

        if ($hoursAgo < self::RECENT_FETCH_THRESHOLD_HOURS) {
            return 'Recently fetched';
        } elseif ($hoursAgo < self::DAILY_FETCH_THRESHOLD_HOURS) {
            return "Fetched {$hoursAgo}h ago";
        } else {
            return 'Fetched '.$this->last_fetched_at->diffForHumans();
        }
    }

    /**
     * @param  Builder<Feed>  $query
     * @return Builder<Feed>
     */
    public function scopeStale(Builder $query, int $thresholdHours): Builder
    {
        return $query->where('is_active', true)
            ->where(function (Builder $query) use ($thresholdHours) {
                $query->whereNull('last_fetched_at')
                    ->orWhere('last_fetched_at', '<', now()->subHours($thresholdHours));
            });
    }

    /**
     * @return BelongsToMany<PlatformChannel, $this>
     */
    public function channels(): BelongsToMany
    {
        return $this->belongsToMany(PlatformChannel::class, 'routes')
            ->withPivot(['is_active', 'priority'])
            ->withTimestamps();
    }

    /**
     * @return BelongsToMany<PlatformChannel, $this>
     */
    public function activeChannels(): BelongsToMany
    {
        return $this->channels()
            ->wherePivot('is_active', true)
            ->orderByPivot('priority', 'desc');
    }

    /**
     * @return HasMany<Article, $this>
     */
    public function articles(): HasMany
    {
        return $this->hasMany(Article::class);
    }

    /**
     * @return BelongsTo<Language, $this>
     */
    public function language(): BelongsTo
    {
        return $this->belongsTo(Language::class);
    }
}
