<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphTo;

/**
 * ContentInteraction Model
 * 
 * Tracks user interactions with content (discussions, replies, answers).
 * Supports likes, helpful votes, bookmarks, and reports.
 * 
 * @property int $id
 * @property string $interactable_type
 * @property int $interactable_id
 * @property int $user_id
 * @property string $interaction_type
 * @property array|null $metadata
 * @property \Carbon\Carbon|null $created_at
 * @property \Carbon\Carbon|null $updated_at
 */
class ContentInteraction extends Model
{
    use HasFactory;

    /**
     * Interaction type constants.
     */
    const TYPE_LIKE = 'like';
    const TYPE_HELPFUL = 'helpful';
    const TYPE_NOT_HELPFUL = 'not_helpful';
    const TYPE_BOOKMARK = 'bookmark';
    const TYPE_SHARE = 'share';
    const TYPE_REPORT = 'report';

    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'interactable_type',
        'interactable_id',
        'user_id',
        'interaction_type',
        'metadata',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'metadata' => 'array',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];

    /**
     * Get the interactable model (discussion, reply, or answer).
     *
     * @return \Illuminate\Database\Eloquent\Relations\MorphTo
     */
    public function interactable(): MorphTo
    {
        return $this->morphTo();
    }

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

    /**
     * Scope a query to filter by interaction type.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param string $type
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeOfType($query, string $type)
    {
        return $query->where('interaction_type', $type);
    }

    /**
     * Scope a query to filter by user.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param int $userId
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeByUser($query, int $userId)
    {
        return $query->where('user_id', $userId);
    }

    /**
     * Scope a query to filter by interactable model.
     *
     * @param \Illuminate\Database\Eloquent\Builder $query
     * @param \Illuminate\Database\Eloquent\Model $model
     * @return \Illuminate\Database\Eloquent\Builder
     */
    public function scopeForModel($query, Model $model)
    {
        return $query->where('interactable_type', get_class($model))
            ->where('interactable_id', $model->id);
    }

    /**
     * Check if user has liked a model.
     *
     * @param \Illuminate\Database\Eloquent\Model $model
     * @param int $userId
     * @return bool
     */
    public static function hasLiked(Model $model, int $userId): bool
    {
        return static::forModel($model)
            ->byUser($userId)
            ->ofType(self::TYPE_LIKE)
            ->exists();
    }

    /**
     * Check if user has marked as helpful.
     *
     * @param \Illuminate\Database\Eloquent\Model $model
     * @param int $userId
     * @return bool
     */
    public static function hasMarkedHelpful(Model $model, int $userId): bool
    {
        return static::forModel($model)
            ->byUser($userId)
            ->ofType(self::TYPE_HELPFUL)
            ->exists();
    }

    /**
     * Check if user has bookmarked.
     *
     * @param \Illuminate\Database\Eloquent\Model $model
     * @param int $userId
     * @return bool
     */
    public static function hasBookmarked(Model $model, int $userId): bool
    {
        return static::forModel($model)
            ->byUser($userId)
            ->ofType(self::TYPE_BOOKMARK)
            ->exists();
    }

    /**
     * Toggle a like interaction.
     *
     * @param \Illuminate\Database\Eloquent\Model $model
     * @param int $userId
     * @return bool True if liked, false if unliked
     */
    public static function toggleLike(Model $model, int $userId): bool
    {
        $existing = static::forModel($model)
            ->byUser($userId)
            ->ofType(self::TYPE_LIKE)
            ->first();

        if ($existing) {
            $existing->delete();
            
            // Decrement like count on model
            if (method_exists($model, 'decrementLikeCount')) {
                $model->decrementLikeCount();
            }
            
            return false;
        }

        static::create([
            'interactable_type' => get_class($model),
            'interactable_id' => $model->id,
            'user_id' => $userId,
            'interaction_type' => self::TYPE_LIKE,
        ]);

        // Increment like count on model
        if (method_exists($model, 'incrementLikeCount')) {
            $model->incrementLikeCount();
        }

        return true;
    }

    /**
     * Toggle a bookmark interaction.
     *
     * @param \Illuminate\Database\Eloquent\Model $model
     * @param int $userId
     * @return bool True if bookmarked, false if unbookmarked
     */
    public static function toggleBookmark(Model $model, int $userId): bool
    {
        $existing = static::forModel($model)
            ->byUser($userId)
            ->ofType(self::TYPE_BOOKMARK)
            ->first();

        if ($existing) {
            $existing->delete();
            return false;
        }

        static::create([
            'interactable_type' => get_class($model),
            'interactable_id' => $model->id,
            'user_id' => $userId,
            'interaction_type' => self::TYPE_BOOKMARK,
        ]);

        return true;
    }

    /**
     * Mark as helpful.
     *
     * @param \Illuminate\Database\Eloquent\Model $model
     * @param int $userId
     * @return bool
     */
    public static function markHelpful(Model $model, int $userId): bool
    {
        // Check for existing helpful or not helpful
        $existing = static::forModel($model)
            ->byUser($userId)
            ->whereIn('interaction_type', [self::TYPE_HELPFUL, self::TYPE_NOT_HELPFUL])
            ->first();

        if ($existing) {
            if ($existing->interaction_type === self::TYPE_HELPFUL) {
                // Already marked helpful, do nothing
                return false;
            }
            
            // Was not helpful, change to helpful
            $existing->update(['interaction_type' => self::TYPE_HELPFUL]);
            
            // Update counts
            if (method_exists($model, 'incrementHelpful')) {
                $model->incrementHelpful();
            }
            
            return true;
        }

        static::create([
            'interactable_type' => get_class($model),
            'interactable_id' => $model->id,
            'user_id' => $userId,
            'interaction_type' => self::TYPE_HELPFUL,
        ]);

        if (method_exists($model, 'incrementHelpful')) {
            $model->incrementHelpful();
        }

        return true;
    }

    /**
     * Mark as not helpful.
     *
     * @param \Illuminate\Database\Eloquent\Model $model
     * @param int $userId
     * @return bool
     */
    public static function markNotHelpful(Model $model, int $userId): bool
    {
        // Check for existing helpful or not helpful
        $existing = static::forModel($model)
            ->byUser($userId)
            ->whereIn('interaction_type', [self::TYPE_HELPFUL, self::TYPE_NOT_HELPFUL])
            ->first();

        if ($existing) {
            if ($existing->interaction_type === self::TYPE_NOT_HELPFUL) {
                // Already marked not helpful, do nothing
                return false;
            }
            
            // Was helpful, change to not helpful
            $existing->update(['interaction_type' => self::TYPE_NOT_HELPFUL]);
            
            // Update counts
            if (method_exists($model, 'incrementNotHelpful')) {
                $model->incrementNotHelpful();
            }
            
            return true;
        }

        static::create([
            'interactable_type' => get_class($model),
            'interactable_id' => $model->id,
            'user_id' => $userId,
            'interaction_type' => self::TYPE_NOT_HELPFUL,
        ]);

        if (method_exists($model, 'incrementNotHelpful')) {
            $model->incrementNotHelpful();
        }

        return true;
    }

    /**
     * Report content.
     *
     * @param \Illuminate\Database\Eloquent\Model $model
     * @param int $userId
     * @param string|null $reason
     * @return static
     */
    public static function report(Model $model, int $userId, ?string $reason = null): static
    {
        return static::create([
            'interactable_type' => get_class($model),
            'interactable_id' => $model->id,
            'user_id' => $userId,
            'interaction_type' => self::TYPE_REPORT,
            'metadata' => $reason ? ['reason' => $reason] : null,
        ]);
    }
}
