<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Validation\ValidationException;

class Recepcion extends Model
{
    // Nombre de tabla coincidente con la migración
    protected $table = 'recepciones';

    protected $fillable = [
        'referencia_type',
        'referencia_id',
        'user_id',
        'cantidad',
        'prendas_defectuosas',
        'fecha_recepcion',
        'notas',
    ];

    protected $casts = [
        'fecha_recepcion' => 'datetime',
        'cantidad' => 'integer',
        'prendas_defectuosas' => 'integer',
    ];

    public function referencia()
    {
        return $this->morphTo();
    }

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

    protected static function booted()
    {
        static::creating(function ($rec) {
            // Cantidad debe ser entero >= 1
            $rec->cantidad = (int) $rec->cantidad;
            $rec->prendas_defectuosas = (int) ($rec->prendas_defectuosas ?? 0);

            if ($rec->cantidad <= 0) {
                throw ValidationException::withMessages(['cantidad' => 'La cantidad debe ser un entero mayor que 0.']);
            }

            if ($rec->prendas_defectuosas < 0) {
                throw ValidationException::withMessages(['prendas_defectuosas' => 'La cantidad de prendas defectuosas no puede ser negativa.']);
            }

            if ($rec->prendas_defectuosas > $rec->cantidad) {
                throw ValidationException::withMessages(['prendas_defectuosas' => 'Las prendas defectuosas no pueden superar la cantidad recibida.']);
            }

            // Fecha por defecto
            if (! $rec->fecha_recepcion) {
                $rec->fecha_recepcion = now();
            }

            // Validación: no permitir sobrepasar la cantidad enviada en la referencia (considerando cobros)
            if ($rec->referencia) {
                $referencia = $rec->referencia;
                $enviada = (int) ($referencia->cantidad_enviada ?? 0);

                // Ya recibido efectivo (cantidad - defectuosos) - arreglos permiten re-recepción
                $yaRecibido = (int) \App\Models\Recepcion::where('referencia_type', get_class($referencia))
                    ->where('referencia_id', $referencia->id)
                    ->sum(\DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)'));
                
                // Los arreglos se restan porque permiten re-recepción cuando regresen
                $arreglos = 0;
                if (method_exists($referencia, 'ajustes')) {
                    $arreglos = (int) $referencia->ajustes()->where('tipo', 'arreglo')->sum('cantidad');
                }
                
                // Los cobros NO permiten más recepciones (son prendas que no llegaron)
                $cobros = 0;
                if (method_exists($referencia, 'cobros')) {
                    $cobros = (int) $referencia->cobros()->sum('cantidad');
                }

                $efectivo = $rec->cantidad - $rec->prendas_defectuosas;
                $yaRecibidoNeto = $yaRecibido - $arreglos;
                $maxPermitido = $enviada - $cobros;
                
                if (($yaRecibidoNeto + $efectivo) > $maxPermitido) {
                    $disponible = max(0, $maxPermitido - $yaRecibidoNeto);
                    throw ValidationException::withMessages([
                        'cantidad' => "La recepción excede lo permitido.
                        
                        📊 Resumen:
                        • Enviadas: {$enviada}
                        • Ya recibidas (neto): {$yaRecibidoNeto}
                        • Cobros registrados: {$cobros}
                        • Arreglos (permiten re-recepción): {$arreglos}
                        • Disponible para recibir: {$disponible}
                        
                        ➡️ Solo puedes recibir {$disponible} prendas más."
                    ]);
                }
            }

            // Set user if available
            if (! $rec->user_id && auth()->check()) {
                $rec->user_id = auth()->id();
            }
        });

        static::created(function ($rec) {
            $rec->syncParentAggregates();

            // Crear un traslado parcial desde la referencia usando esta recepción
            if ($rec->referencia) {
                $referencia = $rec->referencia;
                $efectivo = (int) ($rec->cantidad - ($rec->prendas_defectuosas ?? 0));
                $payload = [
                    'cantidad_enviada' => $rec->cantidad,
                    'cantidad_recibida' => $efectivo,
                    'fecha_recepcion' => $rec->fecha_recepcion,
                    'notas' => 'Creado desde recepción #' . $rec->id . ($rec->notas ? (" - " . $rec->notas) : ''),
                    'prendas_defectuosas' => $rec->prendas_defectuosas ?? 0,
                ];

                // Map destino según tipo de referencia
                if ($referencia instanceof Confeccion) {
                    $origen = 'confeccion';
                    $destino = 'tintoreria';
                } elseif ($referencia instanceof Tintoreria) {
                    $origen = 'tintoreria';
                    $destino = 'acabados';
                } else {
                    $origen = 'referencia';
                    $destino = 'bodega';
                }

                \App\Models\TrasladoPrenda::crearDesdeReferencia($referencia, $origen, $destino, $payload);

                // Avanzar OP por seguridad
                $referencia->ordenProduccion?->avanzarEstado();
            }
        });


        static::updated(function ($rec) {
            $rec->syncParentAggregates();
        });

        static::deleted(function ($rec) {
            $rec->syncParentAggregates();
        });
    }

    public function syncParentAggregates()
    {
        if (! $this->referencia) return;
        $referencia = $this->referencia;

        $sum = (int) static::where('referencia_type', get_class($referencia))
            ->where('referencia_id', $referencia->id)
            ->sum(\DB::raw('cantidad - COALESCE(prendas_defectuosas, 0)'));

        $referencia->cantidad_recibida = $sum;
        $referencia->save();
    }
}
