<?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\Database\Eloquent\Relations\MorphMany;
use Illuminate\Support\Str;

/**
 * Model: RForumThread (Forum Discussion Thread)
 * 
 * Represents discussion threads in the networking forum.
 * Supports categories, visibility levels, and moderation.
 * 
 * @property int $id
 * @property int $user_id
 * @property int|null $partner_id
 * @property string $title
 * @property string $slug
 * @property string $content
 * @property string $category
 * @property string $visibility
 * @property string $status
 * @property bool $is_locked
 * @property bool $is_pinned
 * @property bool $is_featured
 * @property int $views_count
 * @property int $replies_count
 * @property int|null $last_reply_user_id
 * @property \Carbon\Carbon|null $last_reply_at
 * @property bool $is_approved
 * @property array|null $tags
 */
class RForumThread extends Model
{
    use HasFactory, SoftDeletes;

    protected $table = 'r_forum_threads';

    protected $fillable = [
        'user_id',
        'partner_id',
        'title',
        'slug',
        'content',
        'category',
        'visibility',
        'status',
        'is_locked',
        'is_pinned',
        'is_featured',
        'views_count',
        'replies_count',
        'last_reply_user_id',
        'last_reply_at',
        'is_approved',
        'approved_by',
        'approved_at',
        'tags',
    ];

    protected $casts = [
        'is_locked' => 'boolean',
        'is_pinned' => 'boolean',
        'is_featured' => 'boolean',
        'views_count' => 'integer',
        'replies_count' => 'integer',
        'last_reply_at' => 'datetime',
        'is_approved' => 'boolean',
        'approved_at' => 'datetime',
        'tags' => 'array',
    ];

    /**
     * Get tags — always returns an array, never null or a raw string.
     * Guards against NULL db values and legacy string-encoded data.
     */
    public function getTagsAttribute(mixed $value): array
    {
        if (is_array($value)) {
            return $value;
        }

        if (is_string($value) && $value !== '') {
            $decoded = json_decode($value, true);
            return is_array($decoded) ? $decoded : [];
        }

        return [];
    }

    /**
     * Category constants.
     */
    const CATEGORY_GENERAL = 'general';
    const CATEGORY_COLLABORATION = 'collaboration';
    const CATEGORY_RESOURCES = 'resources';
    const CATEGORY_EVENTS = 'events';
    const CATEGORY_ANNOUNCEMENTS = 'announcements';
    const CATEGORY_QUESTIONS = 'questions';
    const CATEGORY_BEST_PRACTICES = 'best_practices';
    const CATEGORY_OPPORTUNITIES = 'opportunities';

    /**
     * Visibility constants.
     */
    const VISIBILITY_PUBLIC = 'public';
    const VISIBILITY_PARTNERS_ONLY = 'partners_only';
    const VISIBILITY_MENTORS_ONLY = 'mentors_only';
    const VISIBILITY_PRIVATE = 'private';

    /**
     * Status constants.
     */
    const STATUS_OPEN = 'open';
    const STATUS_CLOSED = 'closed';
    const STATUS_ARCHIVED = 'archived';
    const STATUS_PINNED = 'pinned';

    /**
     * Get the thread author.
     */
    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    /**
     * Get the partner (for partner-specific threads).
     */
    public function partner(): BelongsTo
    {
        return $this->belongsTo(RPartner::class, 'partner_id');
    }

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

    /**
     * Get all replies.
     */
    public function replies(): HasMany
    {
        return $this->hasMany(RForumReply::class, 'thread_id')
                    ->whereNull('parent_id')
                    ->orderBy('created_at');
    }

    /**
     * Get all replies including nested.
     */
    public function allReplies(): HasMany
    {
        return $this->hasMany(RForumReply::class, 'thread_id');
    }

    /**
     * Get file attachments for this thread.
     */
    public function attachments(): MorphMany
    {
        return $this->morphMany(RForumAttachment::class, 'attachable');
    }

    /**
     * Scope: Open threads.
     */
    public function scopeOpen($query)
    {
        return $query->where('status', self::STATUS_OPEN);
    }

    /**
     * Scope: Pinned threads.
     */
    public function scopePinned($query)
    {
        return $query->where('is_pinned', true);
    }

    /**
     * Scope: Featured threads.
     */
    public function scopeFeatured($query)
    {
        return $query->where('is_featured', true);
    }

    /**
     * Scope: Approved threads.
     */
    public function scopeApproved($query)
    {
        return $query->where('is_approved', true);
    }

    /**
     * Scope: Public visibility.
     */
    public function scopePublic($query)
    {
        return $query->where('visibility', self::VISIBILITY_PUBLIC);
    }

    /**
     * Scope: By category.
     */
    public function scopeByCategory($query, string $category)
    {
        return $query->where('category', $category);
    }

    /**
     * Scope: For partners.
     */
    public function scopeForPartners($query)
    {
        return $query->whereIn('visibility', [
            self::VISIBILITY_PUBLIC, 
            self::VISIBILITY_PARTNERS_ONLY
        ]);
    }

    /**
     * Scope: For mentors.
     */
    public function scopeForMentors($query)
    {
        return $query->whereIn('visibility', [
            self::VISIBILITY_PUBLIC, 
            self::VISIBILITY_MENTORS_ONLY
        ]);
    }

    /**
     * Scope: Recent activity.
     */
    public function scopeRecentActivity($query)
    {
        return $query->orderByDesc('last_reply_at')
                     ->orderByDesc('updated_at');
    }

    /**
     * Check if thread is locked.
     */
    public function isLocked(): bool
    {
        return $this->is_locked || $this->status === self::STATUS_CLOSED;
    }

    /**
     * Check if can reply.
     */
    public function canReply(): bool
    {
        return !$this->isLocked() && $this->is_approved;
    }

    /**
     * Check if user is author.
     */
    public function isAuthor(int $userId): bool
    {
        return $this->user_id === $userId;
    }

    /**
     * Increment view count.
     */
    public function incrementViews(): void
    {
        $this->increment('views_count');
    }

    /**
     * Update reply stats.
     */
    public function updateReplyStats(): void
    {
        $lastReply = $this->allReplies()
                          ->where('status', RForumReply::STATUS_PUBLISHED)
                          ->latest()
                          ->first();

        $this->update([
            'replies_count' => $this->allReplies()->count(),
            'last_reply_user_id' => $lastReply?->user_id,
            'last_reply_at' => $lastReply?->created_at,
        ]);
    }

    /**
     * Lock the thread.
     */
    public function lock(): void
    {
        $this->update([
            'is_locked' => true,
            'status' => self::STATUS_CLOSED,
        ]);
    }

    /**
     * Unlock the thread.
     */
    public function unlock(): void
    {
        $this->update([
            'is_locked' => false,
            'status' => self::STATUS_OPEN,
        ]);
    }

    /**
     * Pin the thread.
     */
    public function pin(): void
    {
        $this->update(['is_pinned' => true]);
    }

    /**
     * Unpin the thread.
     */
    public function unpin(): void
    {
        $this->update(['is_pinned' => false]);
    }

    /**
     * Get category label.
     */
    public function getCategoryLabelAttribute(): string
    {
        return match($this->category) {
            self::CATEGORY_GENERAL => 'General Discussion',
            self::CATEGORY_COLLABORATION => 'Collaboration',
            self::CATEGORY_RESOURCES => 'Resources',
            self::CATEGORY_EVENTS => 'Events',
            self::CATEGORY_ANNOUNCEMENTS => 'Announcements',
            self::CATEGORY_QUESTIONS => 'Questions & Answers',
            self::CATEGORY_BEST_PRACTICES => 'Best Practices',
            self::CATEGORY_OPPORTUNITIES => 'Opportunities',
            default => ucfirst($this->category),
        };
    }

    /**
     * Get status color.
     */
    public function getStatusColorAttribute(): string
    {
        return match($this->status) {
            self::STATUS_OPEN => 'green',
            self::STATUS_CLOSED => 'gray',
            self::STATUS_ARCHIVED => 'red',
            self::STATUS_PINNED => 'blue',
            default => 'gray',
        };
    }

    /**
     * Generate slug from title.
     */
    public static function generateSlug(string $title): string
    {
        $slug = Str::slug($title);
        $count = static::where('slug', 'LIKE', "{$slug}%")->count();
        
        return $count > 0 ? "{$slug}-{$count}" : $slug;
    }
}
