<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class InventarioPrenda extends Model
{
    protected $fillable = [
        'orden_produccion_id',
        'cantidad_terminada',
        'cantidad_disponible',
        'fecha_ingreso',
        'estado',
        'producto_id',
    ];

    public function ordenProduccion()
    {
        return $this->belongsTo(OrdenProduccion::class);
    }

    public function producto()
    {
        return $this->belongsTo(\App\Models\Producto::class, 'producto_id');
    }

    public function distribuciones()
    {
        return $this->hasMany(\App\Models\InventarioPrendaDistribucion::class, 'inventario_prenda_id');
    }

    protected static function booted()
    {
        static::creating(function ($inventario) {
            // Sincronizar producto desde la Orden de Producción si no se especificó
            if ($inventario->orden_produccion_id && ! $inventario->producto_id) {
                $op = \App\Models\OrdenProduccion::find($inventario->orden_produccion_id);
                if ($op && $op->producto_id) {
                    $inventario->producto_id = $op->producto_id;
                }
            }

            // Validar conflicto: si el OP tiene producto y difiere del seleccionado, bloquear
            if ($inventario->producto_id && $inventario->orden_produccion_id) {
                $op = \App\Models\OrdenProduccion::find($inventario->orden_produccion_id);
                if ($op && $op->producto_id && $op->producto_id != $inventario->producto_id) {
                    throw \Illuminate\Validation\ValidationException::withMessages([
                        'producto_id' => 'El producto seleccionado difiere del producto asociado a la Orden de Producción (fuente de verdad).',
                    ]);
                }
            }

            // Validación y auto-filling: la cantidad terminada se calcula automáticamente desde lo recibido para esta OP (traslados a bodega)
            if ($inventario->orden_produccion_id) {
                // Total recibido considerando procesos de acabados que se han recibido
                $totalRecibido = \App\Models\ProcesoAcabado::where('orden_produccion_id', $inventario->orden_produccion_id)
                    ->whereNotNull('fecha_recepcion')
                    ->sum('cantidad_recibida');

                $assigned = \App\Models\InventarioPrenda::where('orden_produccion_id', $inventario->orden_produccion_id)->sum('cantidad_terminada');

                $available = max(0, (int) $totalRecibido - (int) $assigned);

                // Si no se proporcionó cantidad_terminada, asignar automáticamente lo disponible
                if (! isset($inventario->cantidad_terminada) || (int) $inventario->cantidad_terminada <= 0) {
                    $inventario->cantidad_terminada = $available;
                }

                if ((int) $inventario->cantidad_terminada > $available) {
                    throw \Illuminate\Validation\ValidationException::withMessages([
                        'cantidad_terminada' => 'No se puede registrar más cantidad terminada de la que está disponible desde acabados/traslados (' . $available . ').',
                    ]);
                }

                if ((int) $inventario->cantidad_terminada <= 0) {
                    throw \Illuminate\Validation\ValidationException::withMessages([
                        'cantidad_terminada' => 'No hay cantidad terminada disponible para esta Orden de Producción.',
                    ]);
                }
            }

            // Fecha de ingreso por defecto a hoy si no se proporcionó
            if (! isset($inventario->fecha_ingreso) || ! $inventario->fecha_ingreso) {
                $inventario->fecha_ingreso = now()->toDateString();
            }

            // Al ingresar al inventario, todo está disponible
            $inventario->cantidad_disponible = $inventario->cantidad_terminada;

            // Estado automático inicial
            $inventario->estado = 'en_bodega';
        });

        // Al crear inventario de prenda, alimentar (incrementar o crear) el stock de Producto
        static::created(function ($inventario) {
            if (! $inventario->cantidad_terminada || $inventario->cantidad_terminada <= 0) {
                return;
            }

            $op = $inventario->ordenProduccion;

            // Priorizar producto explícito si fue seleccionado
            if ($inventario->producto_id) {
                $producto = \App\Models\Producto::find($inventario->producto_id);
                if ($producto && ! $producto->variants()->exists()) {
                    $producto->increment('stock', $inventario->cantidad_terminada);
                }
                return;
            }

            if (! $op) {
                return;
            }

            // Intentar emparejar producto por nombre de prenda_modelo o referencia
            $nombre = $op->prenda_modelo ?? $op->referencia ?? null;
            if (! $nombre) {
                return;
            }

            $producto = \App\Models\Producto::where('nombre', $nombre)->first();

            // Si existe y no tiene variantes, incrementar stock
            if ($producto) {
                if (! $producto->variants()->exists()) {
                    // Si el producto usa bodegas, sumar al stock directo (simplificado)
                    $producto->increment('stock', $inventario->cantidad_terminada);
                } else {
                    // Tiene variantes: no hacemos cambios automáticos aquí (se requiere asignación manual)
                    // Podríamos implementar reglas adicionales si se definieran las variantes en la OP
                }

                return;
            }

            // Si no existe el producto, crearlo automáticamente con stock inicial
            $codigo = 'AUTOP-' . $op->id . '-' . time();
            $codigo = substr($codigo, 0, 50);

            // Asegurar unicidad del codigo_barras
            while (\App\Models\Producto::where('codigo_barras', $codigo)->exists()) {
                $codigo .= '-' . rand(0, 9);
                $codigo = substr($codigo, 0, 50);
            }

            \App\Models\Producto::create([
                'nombre' => $nombre,
                'descripcion' => 'Creado automáticamente desde InventarioPrenda (OP #' . $op->id . ')',
                'stock' => $inventario->cantidad_terminada,
                'estado' => true,
                'precio_compra' => 0,
                'precio_venta' => 0,
                'unidad_medida' => 'unidad',
                'codigo_barras' => $codigo,
                'categoria_id' => \App\Models\Categoria::first()?->id ?? \App\Models\Categoria::create(['nombre' => 'Generica'])->id,
            ]);
        });
    }
}
