<?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\HasOne;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;

class Message extends BaseModel
{
    protected $fillable = [
        'conversation_id',
        'user_id',
        'type',
        'content',
        'metadata',
        'client_generated_id',
        'reply_to_message_id',
        'edited_at',
        'is_deleted',
        'deleted_at',
    ];

    protected $casts = [
        'metadata' => 'array',
        'edited_at' => 'datetime',
        'is_deleted' => 'boolean',
        'deleted_at' => 'datetime',
    ];

    protected $with = ['attachments'];

    public function conversation(): BelongsTo
    {
        return $this->belongsTo(Conversation::class);
    }

    public function user(): BelongsTo
    {
        return $this->belongsTo(User::class);
    }

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

    public function replies(): HasMany
    {
        return $this->hasMany(Message::class, 'reply_to_message_id')
            ->where('is_deleted', false);
    }

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

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

    // Scopes
    public function scopeNotDeleted(Builder $query): Builder
    {
        return $query->where('is_deleted', false);
    }

    public function scopeInConversation(Builder $query, int $conversationId): Builder
    {
        return $query->where('conversation_id', $conversationId);
    }

    public function scopeVisibleTo(Builder $query, ?int $userId = null): Builder
    {
        $userId = $userId ?? Auth::id();
        
        return $query->whereHas('conversation', function ($q) use ($userId) {
            $q->visibleTo($userId);
        });
    }

    public function scopeWithReceipts(Builder $query, ?int $userId = null): Builder
    {
        $userId = $userId ?? Auth::id();
        
        return $query->with(['receipts' => function ($q) use ($userId) {
            $q->where('user_id', '!=', $userId);
        }]);
    }

    public function scopeCursorPaginate(Builder $query, ?int $cursor = null, int $limit = 50): Builder
    {
        if ($cursor) {
            $query->where('id', '<', $cursor);
        }
        
        return $query->orderBy('id', 'desc')->limit($limit);
    }

    // Helper methods
    public function markAsDelivered(int $userId): void
    {
        $this->receipts()->updateOrCreate(
            ['user_id' => $userId, 'type' => 'delivered'],
            ['receipt_at' => now()]
        );
    }

    public function markAsSeen(int $userId): void
    {
        $this->receipts()->updateOrCreate(
            ['user_id' => $userId, 'type' => 'seen'],
            ['receipt_at' => now()]
        );

        // Also mark as delivered if not already
        $this->markAsDelivered($userId);
    }

    public function softDelete(): void
    {
        $this->update([
            'is_deleted' => true,
            'deleted_at' => now(),
            'content' => null,
        ]);
    }

    public function edit(string $newContent): void
    {
        $this->update([
            'content' => $newContent,
            'edited_at' => now(),
        ]);
    }

    public function isEdited(): bool
    {
        return !is_null($this->edited_at);
    }

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

    public function hasAttachments(): bool
    {
        return $this->attachments()->exists();
    }

    public function getDeliveryStatus(): array
    {
        $participants = $this->conversation->participants()
            ->where('user_id', '!=', $this->user_id)
            ->with('user')
            ->get();

        $deliveredTo = $this->receipts()
            ->where('type', 'delivered')
            ->pluck('user_id')
            ->toArray();

        $seenBy = $this->receipts()
            ->where('type', 'seen')
            ->pluck('user_id')
            ->toArray();

        return [
            'total_participants' => $participants->count(),
            'delivered_count' => count($deliveredTo),
            'seen_count' => count($seenBy),
            'delivered_to' => $deliveredTo,
            'seen_by' => $seenBy,
        ];
    }

    public static function createSystemMessage(int $conversationId, string $content, array $metadata = []): self
    {
        return self::create([
            'conversation_id' => $conversationId,
            'user_id' => 1, // System user
            'type' => 'system',
            'content' => $content,
            'metadata' => $metadata,
        ]);
    }
}
