<?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;

/**
 * DiscussionReply Model
 * 
 * Represents a reply to a discussion post.
 * Supports threaded/nested replies with parent-child relationships.
 * 
 * @property int $id
 * @property string $content
 * @property int $discussion_id
 * @property int $user_id
 * @property int|null $parent_id
 * @property bool $is_active
 * @property bool $is_accepted_answer
 * @property int $like_count
 * @property int $depth
 * @property \Carbon\Carbon|null $created_at
 * @property \Carbon\Carbon|null $updated_at
 * @property \Carbon\Carbon|null $deleted_at
 */
class DiscussionReply extends Model
{
    use HasFactory, SoftDeletes;

    /**
     * Maximum depth for nested replies.
     */
    const MAX_DEPTH = 3;

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'content',
        'discussion_id',
        'user_id',
        'parent_id',
        'is_active',
        'is_accepted_answer',
        'like_count',
        'depth',
    ];

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

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

    /**
     * The "booted" method of the model.
     */
    protected static function booted(): void
    {
        static::creating(function (self $reply) {
            // Set depth based on parent
            if ($reply->parent_id) {
                $parent = static::find($reply->parent_id);
                $reply->depth = $parent ? min($parent->depth + 1, self::MAX_DEPTH) : 0;
            } else {
                $reply->depth = 0;
            }
        });

        static::created(function (self $reply) {
            // Update discussion stats
            $reply->discussion->updateReplyStats();
        });

        static::updated(function (self $reply) {
            // Update discussion stats if active status changed
            if ($reply->isDirty('is_active')) {
                $reply->discussion->updateReplyStats();
            }
        });

        static::deleted(function (self $reply) {
            // Update discussion stats
            $reply->discussion->updateReplyStats();
        });
    }

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

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

    /**
     * Get the parent reply (for threaded replies).
     *
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     */
    public function parent(): BelongsTo
    {
        return $this->belongsTo(static::class, 'parent_id');
    }

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

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

    /**
     * Scope a query to only include active replies.
     *
     * @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 top-level replies.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeTopLevel($query)
    {
        return $query->whereNull('parent_id');
    }

    /**
     * Scope a query to only include accepted answers.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeAccepted($query)
    {
        return $query->where('is_accepted_answer', true);
    }

    /**
     * Scope a query to order by most liked.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeMostLiked($query)
    {
        return $query->orderByDesc('like_count');
    }

    /**
     * Check if reply is top-level (no parent).
     *
     * @return bool
     */
    public function isTopLevel(): bool
    {
        return is_null($this->parent_id);
    }

    /**
     * Check if reply can have nested replies.
     *
     * @return bool
     */
    public function canNest(): bool
    {
        return $this->depth < self::MAX_DEPTH;
    }

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

    /**
     * Increment the like count.
     *
     * @return void
     */
    public function incrementLikeCount(): void
    {
        $this->increment('like_count');
    }

    /**
     * Decrement the like count.
     *
     * @return void
     */
    public function decrementLikeCount(): void
    {
        $this->decrement('like_count');
    }

    /**
     * Get content preview for display.
     *
     * @return string
     */
    public function getContentPreviewAttribute(): string
    {
        return \Illuminate\Support\Str::limit(strip_tags($this->content), 150);
    }

    /**
     * Get time ago string.
     *
     * @return string
     */
    public function getTimeAgoAttribute(): string
    {
        return $this->created_at->diffForHumans();
    }

    /**
     * Get all nested replies recursively.
     *
     * @return \Illuminate\Database\Eloquent\Collection
     */
    public function getAllReplies()
    {
        return $this->activeReplies()->with('user', 'replies.user')->get();
    }

    /**
     * Mark this reply as the accepted answer.
     *
     * @return void
     */
    public function markAsAccepted(): void
    {
        // Remove accepted status from other replies in this discussion
        static::where('discussion_id', $this->discussion_id)
            ->where('is_accepted_answer', true)
            ->update(['is_accepted_answer' => false]);

        // Mark this reply as accepted
        $this->update(['is_accepted_answer' => true]);
    }
}
