<?php

namespace App\Models\Messenger;

use App\Models\User;
use App\Models\BaseModel;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;

class Conversation extends BaseModel
{
    protected $fillable = [
        'type',
        'title',
        'description',
        'avatar',
        'created_by',
        'last_message_id',
        'last_activity_at',
        'settings',
        'is_archived',
    ];

    protected $casts = [
        'last_activity_at' => 'datetime',
        'settings' => 'array',
        'is_archived' => 'boolean',
    ];

    protected $with = ['lastMessage'];

    public function creator(): BelongsTo
    {
        return $this->belongsTo(User::class, 'created_by');
    }

    public function lastMessage(): BelongsTo
    {
        return $this->belongsTo(Message::class, 'last_message_id');
    }

    public function messages(): HasMany
    {
        return $this->hasMany(Message::class)
            ->where('is_deleted', false)
            ->orderBy('created_at', 'desc');
    }

    public function participants(): HasMany
    {
        return $this->hasMany(ConversationParticipant::class)
            ->whereNull('left_at');
    }

    public function allParticipants(): HasMany
    {
        return $this->hasMany(ConversationParticipant::class);
    }

    public function users(): BelongsToMany
    {
        return $this->belongsToMany(User::class, 'conversation_participants')
            ->whereNull('conversation_participants.left_at')
            ->withPivot(['role', 'joined_at', 'last_seen_at', 'last_seen_message_id', 'is_muted'])
            ->withTimestamps();
    }

    // Scopes
    public function scopeVisibleTo(Builder $query, ?int $userId = null): Builder
    {
        $userId = $userId ?? Auth::id();
        
        return $query->whereHas('participants', function ($q) use ($userId) {
            $q->where('user_id', $userId);
        });
    }

    public function scopeWithUnreadCount(Builder $query, ?int $userId = null): Builder
    {
        $userId = $userId ?? Auth::id();
        
        return $query->withCount(['messages as unread_count' => function ($q) use ($userId) {
            $q->where('is_deleted', false)
                ->whereNotExists(function ($subQ) use ($userId) {
                    $subQ->selectRaw(1)
                        ->from('message_receipts')
                        ->whereColumn('message_receipts.message_id', 'messages.id')
                        ->where('message_receipts.user_id', $userId)
                        ->where('message_receipts.type', 'seen');
                });
        }]);
    }

    public function scopeForUser(Builder $query, int $userId): Builder
    {
        return $query->visibleTo($userId)
            ->withUnreadCount($userId)
            ->orderBy('last_activity_at', 'desc');
    }

    // Helper methods
    public function isParticipant(int $userId): bool
    {
        return $this->participants()->where('user_id', $userId)->exists();
    }

    public function getParticipant(int $userId): ?ConversationParticipant
    {
        return $this->participants()->where('user_id', $userId)->first();
    }

    public function addParticipant(int $userId, string $role = 'member'): ConversationParticipant
    {
        return $this->participants()->updateOrCreate(
            ['user_id' => $userId],
            ['role' => $role, 'joined_at' => now(), 'left_at' => null]
        );
    }

    public function removeParticipant(int $userId): bool
    {
        return $this->participants()
            ->where('user_id', $userId)
            ->update(['left_at' => now()]);
    }

    public function updateLastActivity(): void
    {
        $this->update(['last_activity_at' => now()]);
    }

    public function isDirectMessage(): bool
    {
        return $this->type === 'dm';
    }

    public function isGroup(): bool
    {
        return $this->type === 'group';
    }

    public function getOtherParticipant(int $userId): ?User
    {
        if (!$this->isDirectMessage()) {
            return null;
        }

        return $this->users()
            ->where('users.id', '!=', $userId)
            ->first();
    }

    public function getDisplayName(int $userId): string
    {
        if ($this->isGroup()) {
            return $this->title ?? 'Group Chat';
        }

        $otherUser = $this->getOtherParticipant($userId);
        return $otherUser ? ($otherUser->first_name . ' ' . $otherUser->last_name) : 'Unknown User';
    }

    public function getDisplayAvatar(int $userId): ?string
    {
        if ($this->isGroup()) {
            return $this->avatar;
        }

        $otherUser = $this->getOtherParticipant($userId);
        return $otherUser?->avatar;
    }
}
