<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class AppSyncQueue extends Model
{
    /**
     * Tabla asociada
     */
    protected $table = 'app_sync_queue';

    /**
     * Clave primaria
     */
    protected $primaryKey = 'sync_id';

    /**
     * Sin timestamps automáticos
     */
    public $timestamps = false;

    /**
     * Operaciones
     */
    const OPERACION_CREATE = 'CREATE';
    const OPERACION_UPDATE = 'UPDATE';
    const OPERACION_DELETE = 'DELETE';

    /**
     * Estados
     */
    const ESTADO_PENDIENTE = 'PENDIENTE';
    const ESTADO_PROCESANDO = 'PROCESANDO';
    const ESTADO_PROCESADO = 'PROCESADO';
    const ESTADO_ERROR = 'ERROR';

    /**
     * Prioridades
     */
    const PRIORIDAD_ALTA = 1;
    const PRIORIDAD_MEDIA = 5;
    const PRIORIDAD_BAJA = 10;

    /**
     * Campos asignables
     */
    protected $fillable = [
        'usuario_id',
        'dispositivo_id',
        'tabla_destino',
        'operacion',
        'data_json',
        'local_id',
        'server_id',
        'estado',
        'error_mensaje',
        'intentos',
        'prioridad',
        'fecha_creacion_local',
    ];

    /**
     * Casting de atributos
     */
    protected function casts(): array
    {
        return [
            'data_json' => 'array',
            'intentos' => 'integer',
            'prioridad' => 'integer',
            'fecha_creacion_local' => 'datetime',
            'fecha_recepcion' => 'datetime',
            'fecha_procesado' => 'datetime',
        ];
    }

    /**
     * Relación con Usuario
     */
    public function usuario()
    {
        return $this->belongsTo(Usuario::class, 'usuario_id', 'usu_id');
    }

    /**
     * Relación con Dispositivo
     */
    public function dispositivo()
    {
        return $this->belongsTo(AppDispositivo::class, 'dispositivo_id', 'dispositivo_id');
    }

    /**
     * Scope pendientes
     */
    public function scopePendientes($query)
    {
        return $query->where('estado', self::ESTADO_PENDIENTE);
    }

    /**
     * Scope procesados
     */
    public function scopeProcesados($query)
    {
        return $query->where('estado', self::ESTADO_PROCESADO);
    }

    /**
     * Scope con error
     */
    public function scopeConError($query)
    {
        return $query->where('estado', self::ESTADO_ERROR);
    }

    /**
     * Scope por usuario
     */
    public function scopePorUsuario($query, int $usuarioId)
    {
        return $query->where('usuario_id', $usuarioId);
    }

    /**
     * Scope por dispositivo
     */
    public function scopePorDispositivo($query, int $dispositivoId)
    {
        return $query->where('dispositivo_id', $dispositivoId);
    }

    /**
     * Scope por tabla destino
     */
    public function scopePorTabla($query, string $tabla)
    {
        return $query->where('tabla_destino', $tabla);
    }

    /**
     * Scope ordenado por prioridad
     */
    public function scopeOrdenPrioridad($query)
    {
        return $query->orderBy('prioridad', 'asc')
            ->orderBy('fecha_creacion_local', 'asc');
    }

    /**
     * Marcar como procesando
     */
    public function marcarProcesando(): bool
    {
        $this->estado = self::ESTADO_PROCESANDO;
        return $this->save();
    }

    /**
     * Marcar como procesado
     */
    public function marcarProcesado(?int $serverId = null): bool
    {
        $this->estado = self::ESTADO_PROCESADO;
        $this->fecha_procesado = now();
        if ($serverId) {
            $this->server_id = $serverId;
        }
        return $this->save();
    }

    /**
     * Marcar error
     */
    public function marcarError(string $error): bool
    {
        $this->estado = self::ESTADO_ERROR;
        $this->error_mensaje = $error;
        $this->intentos++;
        return $this->save();
    }

    /**
     * Reintentar
     */
    public function reintentar(): bool
    {
        $this->estado = self::ESTADO_PENDIENTE;
        $this->error_mensaje = null;
        return $this->save();
    }

    /**
     * Verificar si puede reintentar
     */
    public function puedeReintentar(): bool
    {
        return $this->intentos < 5;
    }

    /**
     * Verificar si está pendiente
     */
    public function estaPendiente(): bool
    {
        return $this->estado === self::ESTADO_PENDIENTE;
    }

    /**
     * Verificar si fue procesado
     */
    public function fueProcesado(): bool
    {
        return $this->estado === self::ESTADO_PROCESADO;
    }

    /**
     * Verificar si tiene error
     */
    public function tieneError(): bool
    {
        return $this->estado === self::ESTADO_ERROR;
    }
}
