<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Support\Str;

/**
 * Discussion Model
 * 
 * Represents a user-generated discussion post in the forum.
 * Each discussion belongs to a topic and can have multiple threaded replies.
 * 
 * @property int $id
 * @property string $title
 * @property string $slug
 * @property string $content
 * @property string|null $excerpt
 * @property int $topic_id
 * @property int $user_id
 * @property string $status
 * @property bool $is_active
 * @property bool $is_pinned
 * @property bool $is_featured
 * @property int $view_count
 * @property int $reply_count
 * @property int $like_count
 * @property string|null $meta_title
 * @property string|null $meta_description
 * @property string|null $meta_keywords
 * @property \Carbon\Carbon|null $last_activity_at
 * @property int|null $last_reply_user_id
 * @property \Carbon\Carbon|null $created_at
 * @property \Carbon\Carbon|null $updated_at
 * @property \Carbon\Carbon|null $deleted_at
 */
class Discussion extends Model
{
    use HasFactory, SoftDeletes;

    /**
     * Status constants for easy reference.
     */
    const STATUS_DRAFT = 'draft';
    const STATUS_PUBLISHED = 'published';
    const STATUS_ARCHIVED = 'archived';
    const STATUS_PENDING_REVIEW = 'pending_review';

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'title',
        'slug',
        'content',
        'excerpt',
        'topic_id',
        'user_id',
        'status',
        'is_active',
        'is_pinned',
        'is_featured',
        'view_count',
        'reply_count',
        'like_count',
        'meta_title',
        'meta_description',
        'meta_keywords',
        'last_activity_at',
        'last_reply_user_id',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'is_active' => 'boolean',
        'is_pinned' => 'boolean',
        'is_featured' => 'boolean',
        'view_count' => 'integer',
        'reply_count' => 'integer',
        'like_count' => 'integer',
        'last_activity_at' => 'datetime',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
        'deleted_at' => 'datetime',
    ];

    /**
     * The attributes that should be appended.
     *
     * @var array<int, string>
     */
    protected $appends = [
        'url',
        'excerpt_preview',
    ];

    /**
     * The "booted" method of the model.
     */
    protected static function booted(): void
    {
        static::creating(function (self $discussion) {
            if (empty($discussion->slug)) {
                $discussion->slug = static::generateUniqueSlug($discussion->title);
            }
            if (empty($discussion->excerpt)) {
                $discussion->excerpt = Str::limit(strip_tags($discussion->content), 200);
            }
            if (empty($discussion->last_activity_at)) {
                $discussion->last_activity_at = now();
            }
        });

        static::updating(function (self $discussion) {
            if ($discussion->isDirty('title') && empty($discussion->slug)) {
                $discussion->slug = static::generateUniqueSlug($discussion->title);
            }
            if ($discussion->isDirty('content')) {
                $discussion->excerpt = Str::limit(strip_tags($discussion->content), 200);
            }
        });
    }

    /**
     * Generate a unique slug for the discussion.
     *
     * @param string $title
     * @return string
     */
    public static function generateUniqueSlug(string $title): string
    {
        $slug = Str::slug($title);
        $count = static::withTrashed()
            ->where('slug', 'like', "{$slug}%")
            ->count();

        return $count > 0 ? "{$slug}-{$count}" : $slug;
    }

    /**
     * Get the topic this discussion belongs to.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function topic(): BelongsTo
    {
        return $this->belongsTo(DiscussionTopic::class, 'topic_id');
    }

    /**
     * Get the user who created this discussion.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

    /**
     * Get all replies for this discussion.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function replies(): HasMany
    {
        return $this->hasMany(DiscussionReply::class, 'discussion_id');
    }

    /**
     * Get top-level replies (no parent) for this discussion.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function topLevelReplies(): HasMany
    {
        return $this->replies()
            ->whereNull('parent_id')
            ->where('is_active', true)
            ->orderBy('created_at');
    }

    /**
     * Get active replies for this discussion.
     *
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function activeReplies(): HasMany
    {
        return $this->replies()->where('is_active', true);
    }

    /**
     * Get the last reply user.
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function lastReplyUser(): BelongsTo
    {
        return $this->belongsTo(User::class, 'last_reply_user_id');
    }

    /**
     * Scope a query to only include active discussions.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeActive($query)
    {
        return $query->where('is_active', true);
    }

    /**
     * Scope a query to only include published discussions.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePublished($query)
    {
        return $query->where('status', self::STATUS_PUBLISHED)
            ->where('is_active', true);
    }

    /**
     * Scope a query to only include featured discussions.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeFeatured($query)
    {
        return $query->where('is_featured', true);
    }

    /**
     * Scope a query to only include pinned discussions.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePinned($query)
    {
        return $query->where('is_pinned', true);
    }

    /**
     * Scope a query to order by latest activity.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeLatestActivity($query)
    {
        return $query->orderByDesc('last_activity_at');
    }

    /**
     * Scope a query to order by popularity.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopePopular($query)
    {
        return $query->orderByDesc('view_count')
            ->orderByDesc('reply_count');
    }

    /**
     * Scope a query to filter by topic.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param int $topicId
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeByTopic($query, int $topicId)
    {
        return $query->where('topic_id', $topicId);
    }

    /**
     * Scope a query to search by title or content.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param string $search
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeSearch($query, string $search)
    {
        return $query->where(function ($q) use ($search) {
            $q->where('title', 'like', "%{$search}%")
                ->orWhere('content', 'like', "%{$search}%");
        });
    }

    /**
     * Increment the view count.
     *
     * @return void
     */
    public function incrementViewCount(): void
    {
        $this->increment('view_count');
    }

    /**
     * Update reply count and last activity.
     *
     * @return void
     */
    public function updateReplyStats(): void
    {
        $this->reply_count = $this->activeReplies()->count();
        $lastReply = $this->activeReplies()->latest()->first();
        
        if ($lastReply) {
            $this->last_activity_at = $lastReply->created_at;
            $this->last_reply_user_id = $lastReply->user_id;
        }
        
        $this->save();
    }

    /**
     * Check if discussion is published.
     *
     * @return bool
     */
    public function isPublished(): bool
    {
        return $this->status === self::STATUS_PUBLISHED && $this->is_active;
    }

    /**
     * Check if discussion belongs to user.
     *
     * @param \App\Models\User $user
     * @return bool
     */
    public function isOwnedBy(User $user): bool
    {
        return $this->user_id === $user->id;
    }

    /**
     * Get the URL for this discussion.
     *
     * @return string
     */
    public function getUrlAttribute(): string
    {
        return route('public.discussions.show', $this->slug);
    }

    /**
     * Get excerpt preview for display.
     *
     * @return string
     */
    public function getExcerptPreviewAttribute(): string
    {
        return $this->excerpt ?? Str::limit(strip_tags($this->content), 200);
    }

    /**
     * Get SEO-friendly meta title.
     *
     * @return string
     */
    public function getSeoTitleAttribute(): string
    {
        return $this->meta_title ?? $this->title . ' - Discussion';
    }

    /**
     * Get SEO-friendly meta description.
     *
     * @return string
     */
    public function getSeoDescriptionAttribute(): string
    {
        return $this->meta_description ?? Str::limit(strip_tags($this->excerpt_preview), 160);
    }

    /**
     * Get reading time in minutes.
     *
     * @return int
     */
    public function getReadingTimeAttribute(): int
    {
        $wordCount = str_word_count(strip_tags($this->content));
        return max(1, (int) ceil($wordCount / 200));
    }
}
