<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Builder;

/**
 * ChatMessage Model
 *
 * Represents an individual message within a chat conversation.
 *
 * Requirements: 4.4, 8.3
 */
class ChatMessage extends Model
{
    /**
     * Sender type constants
     */
    const SENDER_AGENT   = 'agent';
    const SENDER_VISITOR = 'visitor';
    const SENDER_SYSTEM  = 'system';

    /**
     * Message type constants
     */
    const TYPE_TEXT   = 'text';
    const TYPE_FILE   = 'file';
    const TYPE_IMAGE  = 'image';
    const TYPE_SYSTEM = 'system';
    const TYPE_AUTO   = 'auto';

    /**
     * System event constants
     */
    const EVENT_AGENT_JOINED          = 'agent_joined';
    const EVENT_AGENT_LEFT            = 'agent_left';
    const EVENT_AGENT_TRANSFERRED     = 'agent_transferred';
    const EVENT_CONVERSATION_STARTED  = 'conversation_started';
    const EVENT_CONVERSATION_ENDED    = 'conversation_ended';
    const EVENT_TYPING                = 'typing';
    const EVENT_SEEN                  = 'seen';

    protected $fillable = [
        'conversation_id',
        'sender_type',
        'sender_id',
        'sender_name',
        'message',
        'type',
        'file_path',
        'file_name',
        'file_mime',
        'file_size',
        'is_delivered',
        'is_read',
        'delivered_at',
        'read_at',
        'is_internal',
        'system_event',
        'reply_to_id',
        'metadata',
    ];

    protected $casts = [
        'is_delivered' => 'boolean',
        'is_read'      => 'boolean',
        'is_internal'  => 'boolean',
        'file_size'    => 'integer',
        'delivered_at' => 'datetime',
        'read_at'      => 'datetime',
        'metadata'     => 'array',
        'created_at'   => 'datetime',
        'updated_at'   => 'datetime',
    ];

    public $timestamps = true;

    // -------------------------------------------------------------------------
    // Relationships
    // -------------------------------------------------------------------------

    public function conversation(): BelongsTo
    {
        return $this->belongsTo(ChatConversation::class, 'conversation_id');
    }

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

    public function parentMessage(): BelongsTo
    {
        return $this->belongsTo(ChatMessage::class, 'reply_to_id');
    }

    public function replies()
    {
        return $this->hasMany(ChatMessage::class, 'reply_to_id');
    }

    // -------------------------------------------------------------------------
    // Scopes
    // -------------------------------------------------------------------------

    public function scopeText(Builder $query): Builder
    {
        return $query->where('type', self::TYPE_TEXT);
    }

    public function scopeFiles(Builder $query): Builder
    {
        return $query->where('type', self::TYPE_FILE);
    }

    public function scopeImages(Builder $query): Builder
    {
        return $query->where('type', self::TYPE_IMAGE);
    }

    public function scopeFromAgent(Builder $query): Builder
    {
        return $query->where('sender_type', self::SENDER_AGENT);
    }

    public function scopeFromVisitor(Builder $query): Builder
    {
        return $query->where('sender_type', self::SENDER_VISITOR);
    }

    public function scopeFromSystem(Builder $query): Builder
    {
        return $query->where('sender_type', self::SENDER_SYSTEM);
    }

    public function scopeVisible(Builder $query): Builder
    {
        return $query->where('is_internal', false);
    }

    public function scopeInternal(Builder $query): Builder
    {
        return $query->where('is_internal', true);
    }

    public function scopeUnread(Builder $query): Builder
    {
        return $query->where('is_read', false);
    }

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

    public function scopeSearch(Builder $query, string $search): Builder
    {
        return $query->where('message', 'like', "%{$search}%");
    }

    // -------------------------------------------------------------------------
    // Boolean helpers
    // -------------------------------------------------------------------------

    public function isFromAgent(): bool
    {
        return $this->sender_type === self::SENDER_AGENT;
    }

    public function isFromVisitor(): bool
    {
        return $this->sender_type === self::SENDER_VISITOR;
    }

    public function isSystemMessage(): bool
    {
        return $this->sender_type === self::SENDER_SYSTEM;
    }

    public function hasAttachment(): bool
    {
        return in_array($this->type, [self::TYPE_FILE, self::TYPE_IMAGE]) && !empty($this->file_path);
    }

    public function isImage(): bool
    {
        return $this->type === self::TYPE_IMAGE;
    }

    public function isFile(): bool
    {
        return $this->type === self::TYPE_FILE;
    }

    public function isInternalNote(): bool
    {
        return $this->is_internal;
    }

    // -------------------------------------------------------------------------
    // Mutators
    // -------------------------------------------------------------------------

    public function markAsDelivered(): void
    {
        $this->update(['is_delivered' => true, 'delivered_at' => now()]);
    }

    public function markAsRead(): void
    {
        $this->update(['is_read' => true, 'read_at' => now()]);
    }

    // -------------------------------------------------------------------------
    // Static factories
    // -------------------------------------------------------------------------

    public static function createSystemMessage(int $conversationId, string $event, string $message, array $metadata = []): self
    {
        return self::create([
            'conversation_id' => $conversationId,
            'sender_type'     => self::SENDER_SYSTEM,
            'message'         => $message,
            'type'            => self::TYPE_SYSTEM,
            'system_event'    => $event,
            'metadata'        => $metadata,
        ]);
    }

    public static function createAgentMessage(int $conversationId, int $agentId, string $message, bool $isInternal = false): self
    {
        $agent = User::find($agentId);

        return self::create([
            'conversation_id' => $conversationId,
            'sender_type'     => self::SENDER_AGENT,
            'sender_id'       => $agentId,
            'sender_name'     => $agent?->name,
            'message'         => $message,
            'type'            => self::TYPE_TEXT,
            'is_internal'     => $isInternal,
        ]);
    }

    public static function createVisitorMessage(int $conversationId, string $message, ?string $visitorName = null): self
    {
        return self::create([
            'conversation_id' => $conversationId,
            'sender_type'     => self::SENDER_VISITOR,
            'sender_name'     => $visitorName,
            'message'         => $message,
            'type'            => self::TYPE_TEXT,
        ]);
    }

    // -------------------------------------------------------------------------
    // Accessors
    // -------------------------------------------------------------------------

    /**
     * Friendly sender display name for use in views.
     */
    public function getSenderDisplayNameAttribute(): string
    {
        if ($this->sender_name) {
            return $this->sender_name;
        }

        if ($this->sender_id && $this->sender) {
            return $this->sender->name;
        }

        if ($this->isFromAgent()) {
            return 'Support Agent';
        }

        if ($this->isSystemMessage()) {
            return 'System';
        }

        return 'Visitor';
    }

    /**
     * CSS bubble classes for admin and public chat views.
     */
    public function getBubbleClassesAttribute(): string
    {
        $base = 'px-4 py-2.5 rounded-2xl text-sm leading-relaxed';

        if ($this->is_internal) {
            return $base . ' bg-yellow-50 border border-yellow-200 text-yellow-800';
        }

        if ($this->isFromAgent()) {
            return $base . ' bg-white border border-gray-200 text-gray-800 rounded-bl-sm';
        }

        if ($this->isFromVisitor()) {
            return $base . ' bg-[#1a4731] text-white rounded-br-sm';
        }

        // System message — no bubble, just centred text
        return 'text-center text-sm text-gray-500 italic';
    }

    /**
     * Message text with HTML line-breaks preserved.
     */
    public function getFormattedMessageAttribute(): string
    {
        return nl2br(e($this->message));
    }

    /**
     * Human-readable file size.
     */
    public function getFormattedFileSizeAttribute(): string
    {
        $bytes = $this->file_size;

        if ($bytes >= 1073741824) return number_format($bytes / 1073741824, 2) . ' GB';
        if ($bytes >= 1048576)    return number_format($bytes / 1048576,    2) . ' MB';
        if ($bytes >= 1024)       return number_format($bytes / 1024,       2) . ' KB';

        return $bytes . ' bytes';
    }

    /**
     * Human-readable time since message.
     */
    public function getTimeAgoAttribute(): string
    {
        return $this->created_at->diffForHumans();
    }

    /**
     * Message type colors for UI.
     */
    public static function typeColors(): array
    {
        return [
            self::TYPE_TEXT   => 'bg-gray-100',
            self::TYPE_FILE   => 'bg-blue-50',
            self::TYPE_IMAGE  => 'bg-green-50',
            self::TYPE_SYSTEM => 'bg-yellow-50',
            self::TYPE_AUTO   => 'bg-purple-50',
        ];
    }
}
