<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Ticket extends Model
{
    use HasFactory;

    protected $fillable = [
        'ticket_number',
        'title',
        'description',
        'project_id',
        'requester_id',
        'assigned_to',
        'status',
        'priority',
        'due_date',
        'resolved_at',
        'closed_at',
        'resolution_notes',
    ];

    protected $casts = [
        'due_date' => 'datetime',
        'resolved_at' => 'datetime',
        'closed_at' => 'datetime',
    ];

    /**
     * Boot the model
     */
    protected static function boot()
    {
        parent::boot();

        static::creating(function ($ticket) {
            if (!$ticket->ticket_number) {
                $ticket->ticket_number = self::generateTicketNumber();
            }
        });
    }

    /**
     * Ticket status constants
     */
    const STATUS_OPEN = 'abierto';
    const STATUS_IN_PROGRESS = 'en_progreso';
    const STATUS_RESOLVED = 'resuelto';
    const STATUS_CLOSED = 'cerrado';

    /**
     * Ticket priority constants
     */
    const PRIORITY_LOW = 'baja';
    const PRIORITY_MEDIUM = 'media';
    const PRIORITY_HIGH = 'alta';
    const PRIORITY_CRITICAL = 'critica';

    /**
     * Get all available statuses
     */
    public static function getStatuses()
    {
        return [
            self::STATUS_OPEN => 'Abierto',
            self::STATUS_IN_PROGRESS => 'En Progreso',
            self::STATUS_RESOLVED => 'Resuelto',
            self::STATUS_CLOSED => 'Cerrado',
        ];
    }

    /**
     * Get all available priorities
     */
    public static function getPriorities()
    {
        return [
            self::PRIORITY_LOW => 'Baja',
            self::PRIORITY_MEDIUM => 'Media',
            self::PRIORITY_HIGH => 'Alta',
            self::PRIORITY_CRITICAL => 'Crítica',
        ];
    }

    /**
     * Get priority color for UI
     */
    public function getPriorityColor()
    {
        switch ($this->priority) {
            case self::PRIORITY_CRITICAL:
                return 'red';
            case self::PRIORITY_HIGH:
                return 'orange';
            case self::PRIORITY_MEDIUM:
                return 'yellow';
            case self::PRIORITY_LOW:
            default:
                return 'green';
        }
    }

    /**
     * Get status color for UI
     */
    public function getStatusColor()
    {
        switch ($this->status) {
            case self::STATUS_OPEN:
                return 'blue';
            case self::STATUS_IN_PROGRESS:
                return 'yellow';
            case self::STATUS_RESOLVED:
                return 'green';
            case self::STATUS_CLOSED:
            default:
                return 'gray';
        }
    }

    /**
     * Get the project this ticket belongs to
     */
    public function project()
    {
        return $this->belongsTo(Project::class);
    }

    /**
     * Get the user who requested this ticket
     */
    public function requester()
    {
        return $this->belongsTo(User::class, 'requester_id');
    }

    /**
     * Get the user assigned to this ticket
     */
    public function assignedUser()
    {
        return $this->belongsTo(User::class, 'assigned_to');
    }

    /**
     * Get comments for this ticket
     */
    public function comments()
    {
        return $this->hasMany(Comment::class)->orderBy('created_at', 'asc');
    }

    /**
     * Get attachments for this ticket
     */
    public function attachments()
    {
        return $this->hasMany(Attachment::class);
    }

    /**
     * Get activity logs for this ticket
     */
    public function activities()
    {
        return $this->hasMany(TicketActivity::class)->orderBy('created_at', 'desc');
    }

    /**
     * Relación con sesiones de trabajo
     */
    public function workSessions()
    {
        return $this->hasMany(TicketWorkSession::class)->orderBy('started_at', 'desc');
    }

    /**
     * Obtener tiempo total invertido en el ticket (todas las sesiones de todos los usuarios)
     */
    public function getTotalWorkTime()
    {
        return $this->workSessions()
            ->whereNotNull('duration_seconds')
            ->sum('duration_seconds');
    }

    /**
     * Obtener tiempo total invertido formateado
     */
    public function getFormattedTotalWorkTime()
    {
        $seconds = $this->getTotalWorkTime();
        return TicketWorkSession::formatDuration($seconds);
    }

    /**
     * Generate unique ticket number
     */
    public static function generateTicketNumber()
    {
        $year = date('Y');
        $month = date('m');
        $lastTicket = self::whereYear('created_at', $year)
                         ->whereMonth('created_at', $month)
                         ->orderBy('id', 'desc')
                         ->first();
        
        $sequence = $lastTicket ? ($lastTicket->id % 10000) + 1 : 1;
        
        return sprintf('TK%s%s%04d', $year, $month, $sequence);
    }

    /**
     * Scope for open tickets
     */
    public function scopeOpen($query)
    {
        return $query->where('status', self::STATUS_OPEN);
    }

    /**
     * Scope for tickets in progress
     */
    public function scopeInProgress($query)
    {
        return $query->where('status', self::STATUS_IN_PROGRESS);
    }

    /**
     * Scope for resolved tickets
     */
    public function scopeResolved($query)
    {
        return $query->where('status', self::STATUS_RESOLVED);
    }

    /**
     * Scope for closed tickets
     */
    public function scopeClosed($query)
    {
        return $query->where('status', self::STATUS_CLOSED);
    }

    /**
     * Scope for high priority tickets
     */
    public function scopeHighPriority($query)
    {
        return $query->whereIn('priority', [self::PRIORITY_HIGH, self::PRIORITY_CRITICAL]);
    }

    /**
     * Check if ticket is overdue
     */
    public function isOverdue()
    {
        return $this->due_date && $this->due_date->isPast() && !in_array($this->status, [self::STATUS_RESOLVED, self::STATUS_CLOSED]);
    }

    /**
     * Get days remaining until due date
     */
    public function getDaysRemaining()
    {
        if (!$this->due_date) {
            return null;
        }

        return now()->diffInDays($this->due_date, false);
    }

    /**
     * Get unread comments count for requester (client)
     */
    public function getUnreadCommentsForRequester()
    {
        return $this->comments()
            ->where('user_id', '!=', $this->requester_id)
            ->where('read_by_requester', false)
            ->count();
    }

    /**
     * Get unread comments count for assigned user
     */
    public function getUnreadCommentsForAssigned()
    {
        if (!$this->assigned_to) {
            return 0;
        }
        
        return $this->comments()
            ->where('user_id', '!=', $this->assigned_to)
            ->where('read_by_assigned', false)
            ->count();
    }

    /**
     * Mark all comments as read for a user
     */
    public function markCommentsAsReadFor($userId)
    {
        if ($userId === $this->requester_id) {
            // Marcar como leído para el solicitante
            $this->comments()
                ->where('user_id', '!=', $userId)
                ->where('read_by_requester', false)
                ->update(['read_by_requester' => true]);
        } elseif ($userId === $this->assigned_to) {
            // Marcar como leído para el asignado
            $this->comments()
                ->where('user_id', '!=', $userId)
                ->where('read_by_assigned', false)
                ->update(['read_by_assigned' => true]);
        }
    }
}