<?php

namespace ViartasCore\Comments\Models;

use Illuminate\Database\Eloquent\SoftDeletes;
use Spatie\Activitylog\Traits\LogsActivity;
use Spatie\Activitylog\LogOptions;
use ViartasCore\Core\Models\BaseModel;

class Comment extends BaseModel
{
    use SoftDeletes, LogsActivity;

    protected $table = 'comments';

    protected $fillable = [
        'commentable_type',
        'commentable_id',
        'parent_id',
        'user_id',
        'guest_name',
        'guest_email',
        'content',
        'rating',
        'status',
        'is_approved',
        'approved_at',
        'approved_by',
        'ip_address',
        'user_agent',
        'metadata',
    ];

    protected $casts = [
        'is_approved' => 'boolean',
        'approved_at' => 'datetime',
        'metadata' => 'array',
        'rating' => 'integer',
    ];

    /**
     * Activity log options
     */
    public function getActivitylogOptions(): LogOptions
    {
        return LogOptions::defaults()
            ->logOnly(['content', 'status', 'is_approved', 'rating'])
            ->logOnlyDirty()
            ->dontSubmitEmptyLogs()
            ->setDescriptionForEvent(fn(string $eventName) => "Comment {$eventName}")
            ->useLogName('comments');
    }

    /**
     * @param $model
     * @return int
     */
    public static function countByModel($model): int
    {
        return static::where('commentable_type', get_class($model))
            ->where('commentable_id', $model->getKey())
            ->count();
    }

    /**
     * Get comment statistics by model
     *
     * @param $model
     * @return array
     */
    public static function statsByModel($model): array
    {
        $query = static::where('commentable_type', get_class($model))
            ->where('commentable_id', $model->getKey());

        return [
            'total' => (clone $query)->count(),
            'approved' => (clone $query)->where('status', self::STATUS_APPROVED)->count(),
            'pending' => (clone $query)->where('status', self::STATUS_PENDING)->count(),
            'rejected' => (clone $query)->where('status', self::STATUS_REJECTED)->count(),
            'spam' => (clone $query)->where('status', self::STATUS_SPAM)->count(),
            'unanswered' => (clone $query)->whereNull('parent_id')->whereDoesntHave('replies')->count(),
        ];
    }

    /**
     * Add parent model info to activity
     */
    public function tapActivity(\Spatie\Activitylog\Contracts\Activity $activity, string $eventName)
    {
        $properties = $activity->properties->toArray();
        $properties['commentable_type'] = $this->getOriginal('commentable_type') ?? $this->commentable_type;
        $properties['commentable_id'] = $this->getOriginal('commentable_id') ?? $this->commentable_id;
        $activity->properties = collect($properties);
    }

    /**
     * Status constants
     */
    const STATUS_PENDING = 'pending';
    const STATUS_APPROVED = 'approved';
    const STATUS_REJECTED = 'rejected';
    const STATUS_SPAM = 'spam';

    /**
     * Get the parent commentable model
     */
    public function commentable()
    {
        return $this->morphTo();
    }

    /**
     * Get the user who approved the comment
     */
    public function approver()
    {
        return $this->belongsTo(config('comments.user_model', 'App\\Models\\User'), 'approved_by');
    }

    /**
     * Get parent comment
     */
    public function parent()
    {
        return $this->belongsTo(self::class, 'parent_id');
    }

    /**
     * Get child comments (replies)
     */
    public function replies()
    {
        return $this->hasMany(self::class, 'parent_id')->orderBy('created_at', 'asc');
    }

    /**
     * Get all nested replies recursively
     */
    public function allReplies()
    {
        return $this->replies()->with('allReplies', 'user');
    }

    /**
     * Scope for approved comments
     */
    public function scopeApproved($query)
    {
        return $query->where('is_approved', true)->where('status', self::STATUS_APPROVED);
    }

    /**
     * Scope for pending comments
     */
    public function scopePending($query)
    {
        return $query->where('status', self::STATUS_PENDING);
    }

    /**
     * Scope for root comments (no parent)
     */
    public function scopeRoot($query)
    {
        return $query->whereNull('parent_id');
    }

    /**
     * Scope for unanswered comments
     */
    public function scopeUnanswered($query)
    {
        return $query->whereNull('parent_id')
            ->whereDoesntHave('replies');
    }

    /**
     * Get author name (user or guest)
     */
    public function getAuthorNameAttribute()
    {
        return $this->user ? $this->user->name : $this->guest_name;
    }

    /**
     * Get author email (user or guest)
     */
    public function getAuthorEmailAttribute()
    {
        return $this->user ? $this->user->email : $this->guest_email;
    }

    /**
     * Get author avatar/initials
     */
    public function getAuthorInitialsAttribute()
    {
        $name = $this->author_name ?? 'Guest';
        $words = explode(' ', $name);
        $initials = '';
        foreach (array_slice($words, 0, 2) as $word) {
            $initials .= mb_substr($word, 0, 1);
        }
        return mb_strtoupper($initials);
    }

    /**
     * Check if comment has replies
     */
    public function hasReplies()
    {
        return $this->replies()->count() > 0;
    }

    /**
     * Approve comment
     */
    public function approve($userId = null)
    {
        $this->update([
            'is_approved' => true,
            'status' => self::STATUS_APPROVED,
            'approved_at' => now(),
            'approved_by' => $userId ?? auth()->id(),
        ]);
    }

    /**
     * Reject comment
     */
    public function reject()
    {
        $this->update([
            'is_approved' => false,
            'status' => self::STATUS_REJECTED,
        ]);
    }

    /**
     * Mark as spam
     */
    public function markAsSpam()
    {
        $this->update([
            'is_approved' => false,
            'status' => self::STATUS_SPAM,
        ]);
    }
}
