<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Solicitud extends Model
{
    // C-06: SoftDeletes — las eliminaciones setean `deleted_at` en lugar de borrar el registro.
    // Esto protege contra pérdida de datos y permite recuperación y auditoría.
    use SoftDeletes;

    protected $table = 'solicitudes';
    protected $fillable = [
        'numero',
        'estado',
        'descripcion',
        'servicio_solicitado',
        'motivo_requerimiento',
        'observaciones',
        'usuario_id',
        'departamento_id',
        'area_trabajo_id',
        'archivo_adjunto',
        'calificacion',
        // Campos exclusivos del módulo de Mantenimiento (FOR-DMPE-008)
        // Solo existen en la BD siser_mantenimiento — son ignorados por Eloquent
        // cuando la tabla no los tiene (módulo Tecnología).
        'tipo_mantenimiento',
        'equipo',
        'serial',
        'placa',
        'tipo_falla',
        'condicion_equipo',
        'genera_odt',
        'descripcion_falla',
        'numero_activo',
        'hora_reporte',
    ];

    protected $casts = [
        'tipo_falla' => 'array',
        'genera_odt' => 'boolean',
    ];

    // #21: $dates fue removido — está deprecado en Laravel 10+.
    // SoftDeletes maneja 'deleted_at' automáticamente.

    // ── A-03: Máquina de estados centralizada ────────────────────────────────
    // Define las transiciones válidas desde cada estado.
    // Cualquier transición no listada aquí será rechazada.
    public const TRANSICIONES_VALIDAS = [
        'I'  => ['A', 'I', 'CE'],        // Ingresada → Asignada, Redirigida (I→I), Cierre admin
        'A'  => ['EE', 'CO', 'EJ', 'I', 'CE'],  // Asignada → En Espera, Ejecutado, En Ejecución, Desasignada, Cierre admin
        'EE' => ['CO', 'A', 'EJ', 'CE'],        // En Espera → Ejecutado, Retomar, En Ejecución, Cierre admin
        'EJ' => ['EE', 'CO', 'EJ', 'A', 'CE'],  // En Ejecución → En Espera, Ejecutado, Avance, Reasignar, Cierre admin
        'CO' => ['CF', 'CE'],             // Ejecutado → Conformada, Cierre admin
        'CF' => ['CE'],                   // Conformada → Cierre Efectivo
        'CE' => [],                       // Cerrada → Estado final (no hay transiciones)
    ];

    // Nombres legibles para mensajes de error
    public const NOMBRES_ESTADO = [
        'I'  => 'Ingresada',
        'A'  => 'Asignada',
        'EJ' => 'En Ejecución',
        'EE' => 'En Espera',
        'CO' => 'Ejecutado/Por Conformar',
        'CF' => 'Conformada',
        'CE' => 'Cerrada',
    ];

    /**
     * Verifica si la solicitud puede transicionar al nuevo estado.
     */
    public function puedeTransicionarA(string $nuevoEstado): bool
    {
        $permitidas = self::TRANSICIONES_VALIDAS[$this->estado] ?? [];
        return in_array($nuevoEstado, $permitidas);
    }

    /**
     * Intenta transicionar al nuevo estado. Retorna false si la transición no es válida.
     * No llama a save() — el controlador decide cuándo persistir.
     */
    public function transicionarA(string $nuevoEstado): bool
    {
        if (!$this->puedeTransicionarA($nuevoEstado)) {
            return false;
        }
        $this->estado = $nuevoEstado;
        return true;
    }

    /**
     * Nombre legible del estado actual.
     */
    public function getNombreEstadoAttribute(): string
    {
        return self::NOMBRES_ESTADO[$this->estado] ?? $this->estado;
    }

    // ── Relaciones ───────────────────────────────────────────────────────────

    public function usuario()
    {
        return $this->belongsTo(User::class, 'usuario_id');
    }

    public function departamento()
    {
        return $this->belongsTo(Departamento::class, 'departamento_id');
    }

    public function areaTrabajo()
    {
        return $this->belongsTo(AreaTrabajo::class, 'area_trabajo_id');
    }

    public function asignaciones()
    {
        return $this->hasMany(Asignacion::class, 'solicitud_id');
    }

    /**
     * A-04: Solo la asignación vigente (activa = true).
     * Retorna la asignación activa actual, o null si no hay ninguna.
     */
    public function asignacionActiva()
    {
        return $this->hasOne(Asignacion::class, 'solicitud_id')->where('activa', true)->latest();
    }

    public function ejecuciones()
    {
        return $this->hasMany(Ejecucion::class, 'solicitud_id');
    }

    public function auditLogs()
    {
        return $this->hasMany(AuditLog::class, 'entidad_id')
                    ->where('entidad_tipo', static::class)
                    ->orderBy('created_at', 'asc');
    }
}
