<?php

namespace App\Models\IndicadoresTi;

use App\Models\UnidadeOrganizacional;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Chamado extends Model
{
    protected $table = 'chamados_ti';

    public const STATUS = [
        'em_andamento' => 'Em Andamento',
        'pendente' => 'Pendente',
        'atendido' => 'Atendido',
        'cancelado' => 'Cancelado / Finalizado',
    ];

    public const PRIORIDADE = [
        'baixa' => 'Baixa',
        'media' => 'Média',
        'alta' => 'Alta',
        'critica' => 'Crítica',
    ];

    public const TIPO = [
        'incidente' => 'Incidente',
        'requisicao' => 'Requisição',
        'problema' => 'Problema',
        'melhoria' => 'Melhoria',
        'help_desk' => 'Help Desk',
    ];

    public const CANAL = [
        'portal' => 'Portal',
        'telefone' => 'Telefone',
        'email' => 'E-mail',
        'presencial' => 'Presencial',
    ];

    protected $fillable = [
        'numero',
        'data_abertura',
        'data_fechamento',
        'data_reabertura',
        'tempo_atendimento',
        'tempo_acumulado',
        'descricao',
        'setor_id',
        'setor_nome',
        'assunto_id',
        'assunto_nome',
        'subassunto_id',
        'subassunto_nome',
        'cliente_id',
        'user_id',
        'atendente_id',
        'status',
        'prioridade',
        'tipo',
        'canal',
        'unidade_organizacional_id',
    ];

    protected $casts = [
        'data_abertura'   => 'datetime',
        'data_fechamento' => 'datetime',
        'data_reabertura' => 'datetime',
    ];

    // =========================
    // RELACIONAMENTOS
    // =========================

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

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

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

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

    // 👇 Usuário que abriu o chamado
    public function solicitante(): BelongsTo
    {
        return $this->belongsTo(User::class, 'user_id');
    }

    // 👇 Usuário que atende o chamado
    public function atendente(): BelongsTo
    {
        return $this->belongsTo(User::class, 'atendente_id');
    }

    public function unidade(): BelongsTo
    {
        return $this->belongsTo(UnidadeOrganizacional::class, 'unidade_organizacional_id');
    }

    public function participantes(): BelongsToMany
    {
        return $this->belongsToMany(User::class, 'chamado_participantes_ti', 'chamado_id', 'user_id')
                    ->withTimestamps();
    }

    public function logs(): HasMany
    {
        return $this->hasMany(ChamadoLog::class)->orderBy('created_at', 'asc');
    }

    public function isParticipante(string $userId): bool
    {
        return $this->atendente_id === $userId
            || $this->participantes->contains('id', $userId);
    }

    // =========================
    // ACCESSORS (INTELIGENTES)
    // =========================

    public function getSolicitanteNomeAttribute(): string
    {
        if ($this->user_id && $this->solicitante) {
            return $this->solicitante->name;
        }

        if ($this->cliente) {
            return $this->cliente->nome;
        }

        return '—';
    }

    public function getSolicitanteTipoAttribute(): string
    {
        if ($this->user_id) {
            return 'usuario';
        }

        if ($this->cliente_id) {
            return 'cliente';
        }

        return 'desconhecido';
    }

    // =========================
    // LÓGICA DE NEGÓCIO
    // =========================

    public static function gerarNumero(): string
    {
        $year = now()->year;
        $ultimoId = (int) static::max('id') + 1;

        return sprintf('CHM-%d-%05d', $year, $ultimoId);
    }

    public function atualizarTempoAtendimento(): void
    {
        if (!$this->data_abertura || !$this->data_fechamento) {
            return;
        }

        // Início do período atual: reopen date if exists, otherwise original opening
        $inicio = Carbon::parse($this->data_reabertura ?? $this->data_abertura);
        $fim    = Carbon::parse($this->data_fechamento);

        $segmentoSegundos = max(0, $inicio->diffInSeconds($fim));
        $this->tempo_acumulado  = ($this->tempo_acumulado ?? 0) + $segmentoSegundos;
        $this->tempo_atendimento = (int) ceil($this->tempo_acumulado / 60);
    }

    private function totalSegundos(): int
    {
        $acumulado = (int) ($this->tempo_acumulado ?? 0);

        if ($this->data_fechamento) {
            return $acumulado;
        }

        // Open: add seconds since the current period started
        $inicio = Carbon::parse($this->data_reabertura ?? $this->data_abertura);
        return $acumulado + max(0, $inicio->diffInSeconds(now()));
    }

    public function getTempoAtendimentoFormatado(): string
    {
        if (!$this->data_abertura) {
            return '—';
        }

        $total = $this->totalSegundos();

        $d = floor($total / 86400);
        $h = floor(($total % 86400) / 3600);
        $m = floor(($total % 3600) / 60);
        $s = $total % 60;

        $partes = [];
        if ($d > 0) $partes[] = $d . 'd';
        if ($h > 0) $partes[] = $h . 'h';
        if ($m > 0) $partes[] = $m . 'min';
        if ($s > 0 || empty($partes)) $partes[] = $s . 's';

        return implode(' ', $partes);
    }

    public function getTempoAtendimentoDetalhado(): array
    {
        if (!$this->data_abertura) {
            return [
                'dias' => 0, 'horas' => 0, 'minutos' => 0, 'segundos' => 0,
                'total_segundos' => 0, 'total_minutos' => 0,
                'formatado' => '—', 'em_andamento' => false,
            ];
        }

        $total = $this->totalSegundos();
        $d     = floor($total / 86400);
        $h     = floor(($total % 86400) / 3600);
        $m     = floor(($total % 3600) / 60);
        $s     = $total % 60;

        return [
            'dias'           => $d,
            'horas'          => $h,
            'minutos'        => $m,
            'segundos'       => $s,
            'total_segundos' => $total,
            'total_minutos'  => (int) ceil($total / 60),
            'formatado'      => $this->getTempoAtendimentoFormatado(),
            'em_andamento'   => is_null($this->data_fechamento),
        ];
    }

    public function isEmAndamento(): bool
    {
        return in_array($this->status, ['pendente', 'em_andamento']);
    }

    public function getTempoAtendimentoLegivelAttribute(): string
    {
        if (!$this->tempo_atendimento) {
            return '—';
        }

        $minutos = $this->tempo_atendimento;

        $dias = floor($minutos / 1440);
        $horas = floor(($minutos % 1440) / 60);
        $mins = $minutos % 60;

        $partes = [];

        if ($dias > 0) $partes[] = $dias . 'd';
        if ($horas > 0) $partes[] = $horas . 'h';
        if ($mins > 0 || empty($partes)) $partes[] = $mins . 'min';

        return implode(' ', $partes);
    }
}