<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\SoftDeletes;

class OrdenLavanderia extends Model
{
    use HasFactory;
    use SoftDeletes;

    protected $table = 'ordenes_lavanderia';

    /**
     * Venta / ticket:
     * - cliente_id: FK opcional al catálogo `clientes` cuando se elige un cliente registrado (relación histórica, reportes).
     * - cliente_nombre y cliente_email: texto copiado en el momento de la venta (ticket, impresión, búsqueda rápida);
     *   si no hay cliente en catálogo solo se guardan estos campos; si hay cliente_id suelen reflejar el mismo contacto al instante de cobrar.
     */
    protected $fillable = [
        'folio_unico',
        'codigo_qr',
        'cliente_nombre',
        'cliente_email',
        'tipo_servicio',
        'detalles_ropa',
        'instrucciones',
        'mostrar_observaciones_en_ticket',
        'total',
        'peso_kg',
        'unidad_cobro',
        'is_priority',
        'current_step',
        'current_step_started_at',
        'lavado_started_at',
        'lavado_finished_at',
        'secado_started_at',
        'secado_finished_at',
        'planchado_started_at',
        'planchado_finished_at',
        'terminado_at',
        'entregado_at',
        'estatus',
        'recepcionista_id',
        'operador_lavado_id',
        'operador_secado_id',
        'operador_planchado_id',
        'entregado_por_id',
        'cancelado_at',
        'cancelado_por_id',
        'motivo_cancelacion',
        'cliente_id',
        'subtotal',
        'impuestos',
        'metodo_pago',
        'caja_id',
        'tipo_servicio_id',
        'fecha_entrega',
        'semaphore_hours_red',
        'semaphore_hours_yellow',
    ];

    protected $casts = [
        'is_priority' => 'boolean',
        'mostrar_observaciones_en_ticket' => 'boolean',
        'current_step_started_at' => 'datetime',
        'lavado_started_at' => 'datetime',
        'lavado_finished_at' => 'datetime',
        'secado_started_at' => 'datetime',
        'secado_finished_at' => 'datetime',
        'planchado_started_at' => 'datetime',
        'planchado_finished_at' => 'datetime',
        'terminado_at' => 'datetime',
        'entregado_at' => 'datetime',
        'cancelado_at' => 'datetime',
        'fecha_entrega' => 'datetime',
        'semaphore_hours_red' => 'integer',
        'semaphore_hours_yellow' => 'integer',
    ];

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

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

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

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

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

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

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

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

    /** Catálogo SLA (urgente, express, normal). No confundir con el atributo texto `tipo_servicio`. */
    public function slaTipoServicio(): BelongsTo
    {
        return $this->belongsTo(TipoServicio::class, 'tipo_servicio_id');
    }

    public function shippingOrder(): HasOne
    {
        return $this->hasOne(ShippingOrder::class, 'orden_lavanderia_id');
    }

    public function detalles(): HasMany
    {
        return $this->hasMany(OrdenLavanderiaDetalle::class, 'orden_lavanderia_id');
    }

    public function pagos(): HasMany
    {
        return $this->hasMany(OrdenLavanderiaPago::class, 'orden_lavanderia_id');
    }

    public function bolsas(): HasMany
    {
        return $this->hasMany(OrdenLavanderiaBolsa::class, 'orden_lavanderia_id')->orderBy('indice');
    }

    public function estadoLogs(): HasMany
    {
        return $this->hasMany(OrdenEstadoLog::class, 'orden_lavanderia_id');
    }

    public function notificacionLogs(): HasMany
    {
        return $this->hasMany(NotificacionLog::class, 'orden_lavanderia_id');
    }

    public function areaPresences(): HasMany
    {
        return $this->hasMany(OrderAreaPresence::class, 'orden_lavanderia_id');
    }

    public function areaScanEvents(): HasMany
    {
        return $this->hasMany(OrderAreaScanEvent::class, 'orden_lavanderia_id');
    }

    public const STEP_RECEPCION = 'recepcion';

    public const STEP_LAVADO = 'lavado';

    public const STEP_SECADO = 'secado';

    public const STEP_PLANCHADO = 'planchado';

    public const STEP_TERMINADO = 'terminado';

    public const STEP_ENTREGADO = 'entregado';

    public const ESTATUS_PENDIENTE = 'pendiente';

    public const ESTATUS_EN_PROCESO = 'en_proceso';

    public const ESTATUS_TERMINADO = 'terminado';

    public const ESTATUS_ENTREGADO = 'entregado';

    public const ESTATUS_CANCELADO = 'cancelado';

    /** Resumen en cabecera cuando hay más de un método en `pagos`. */
    public const METODO_MIXTO = 'mixto';

    /**
     * Filtros del historial de ventas/tickets (listado paginado y export CSV — §25).
     *
     * @param  array<string, mixed>  $filters
     */
    public function scopeHistorialFilters(Builder $query, array $filters): Builder
    {
        if (! empty($filters['estatus'])) {
            $query->where('estatus', $filters['estatus']);
        }

        if (! empty($filters['current_step'])) {
            $query->where('current_step', $filters['current_step']);
        }

        if (! empty($filters['cliente_nombre'])) {
            $query->where('cliente_nombre', 'like', '%'.$filters['cliente_nombre'].'%');
        }

        if (! empty($filters['folio_unico'])) {
            $query->where('folio_unico', 'like', '%'.$filters['folio_unico'].'%');
        }

        if (array_key_exists('is_priority', $filters) && $filters['is_priority'] !== null && $filters['is_priority'] !== '') {
            $query->where('is_priority', filter_var($filters['is_priority'], FILTER_VALIDATE_BOOLEAN));
        }

        if (! empty($filters['tipo_servicio_id'])) {
            $query->where('tipo_servicio_id', (int) $filters['tipo_servicio_id']);
        }

        if (! empty($filters['caja_id'])) {
            $query->where('caja_id', (int) $filters['caja_id']);
        }

        if (! empty($filters['created_from'])) {
            $query->whereDate('created_at', '>=', $filters['created_from']);
        }

        if (! empty($filters['created_to'])) {
            $query->whereDate('created_at', '<=', $filters['created_to']);
        }

        if (! empty($filters['recepcionista_id'])) {
            $query->where('recepcionista_id', (int) $filters['recepcionista_id']);
        }

        return $query;
    }
}
