<?php

namespace App\Filament\Pages;

use App\Models\Caja;
use App\Models\Cliente;
use App\Models\MovimientoCaja;
use Filament\Pages\Page;
use Filament\Forms;
use Filament\Tables;
use App\Models\Producto;
use App\Models\ProductVariant;
use App\Models\Venta;
use Livewire\Component;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Mail;

class PuntoVenta extends Page
{
    protected static ?string $navigationGroup = 'Operación';
    protected static ?int $navigationSort = 120;
    protected static ?string $navigationIcon = 'heroicon-o-shopping-cart';
    protected static string $view = 'filament.pages.punto-venta';

    public $barcodeBusqueda = '';

    public $productos = [];
    public $carrito = [];
    public $total = 0;
    public $tipo_pago = 'Efectivo';

    public $numeroDocumentoCliente = '';
    public $datosCliente = [
        'nombre' => null,
        'correo' => null,
        'telefono' => null,
    ];
    public $cliente_id = null;

    public $correoCotizacion = '';
    public $bodega_id = null; // Bodega seleccionada para la venta

    public function mount()
    {
        $this->productos = Producto::where('estado', true)
            ->where(function ($query) {
                $query->where('stock', '>', 0)
                    ->orWhereHas('bodegas', function ($q) {
                        $q->where('producto_bodega.stock', '>', 0);
                    })
                    ->orWhereHas('variants', function ($q) {
                        $q->where('stock', '>', 0)
                            ->orWhereHas('bodegas', function ($bq) {
                                $bq->where('variante_bodega.stock', '>', 0);
                            });
                    });
            })
            ->with('variants.color', 'variants.size', 'bodegas')
            ->limit(20)
            ->get();
        
        // Seleccionar bodega "Principal" por defecto
        $bodegaPrincipal = \App\Models\Bodega::where('nombre', 'Principal')->first();
        $this->bodega_id = $bodegaPrincipal ? $bodegaPrincipal->id : null;
    }

    public function agregarAlCarrito($productoId, $tipo)
    {
        if ($tipo == 'p') {
            $producto = Producto::find($productoId);
            if (!$producto)
                return;

            $key = 'p-' . $producto->id;

            if (!isset($this->carrito[$key])) {
                $this->carrito[$key] = [
                    'id' => $producto->id,
                    'nombre' => $producto->nombre,
                    'precio_venta' => $producto->precio_venta,
                    'precio_original' => $producto->precio_venta,
                    'precio_modificado' => $producto->precio_venta,
                    'cantidad' => 1,
                    'tipo' => 'p',
                ];
            } else {
                $this->carrito[$key]['cantidad']++;
            }
        } else {
            $producto = ProductVariant::find($productoId);
            if (!$producto)
                return;

            $key = 'v-' . $producto->id;

            if (!isset($this->carrito[$key])) {
                $this->carrito[$key] = [
                    'id' => $producto->producto->id,
                    'nombre' => $producto->producto->nombre,
                    'precio_venta' => $producto->producto->precio_venta,
                    'precio_original' => $producto->producto->precio_venta,
                    'precio_modificado' => $producto->producto->precio_venta,
                    'variante' => 'Color: ' . $producto->color->name . ', Talla: ' . $producto->size->name,
                    'variante_id' => $producto->id,
                    'cantidad' => 1,
                    'tipo' => 'v',
                ];
            } else {
                $this->carrito[$key]['cantidad']++;
            }
        }

        $this->calcularTotal();
    }


    public function calcularTotal()
    {
        $this->total = collect($this->carrito)->sum(fn($item) => $item['precio_modificado'] * $item['cantidad']);
    }

    public function actualizarPrecio($key, $nuevoPrecio)
    {
        if (isset($this->carrito[$key])) {
            // Validar que el precio sea válido (mayor o igual a 0)
            $precio = floatval($nuevoPrecio);
            if ($precio >= 0) {
                $this->carrito[$key]['precio_modificado'] = $precio;
                $this->calcularTotal();
            }
        }
    }

    public function procesarVenta()
    {
        if (empty($this->carrito)) {
            session()->flash('error', 'No se puede procesar la venta: el carrito está vacío.');
            return;
        }

        DB::beginTransaction();
        try {
            $clienteId = null;
            
            if ($this->numeroDocumentoCliente) {
                $cliente = Cliente::where('numero_documento', $this->numeroDocumentoCliente)->first();

                if (!$cliente) {
                    $datosCliente = [
                        'nombre' => $this->datosCliente['nombre'] ?? "Cliente General",
                        'correo' => $this->datosCliente['correo'] ?? null,
                        'telefono' => $this->datosCliente['telefono'] ?? null,
                        'numero_documento' => $this->numeroDocumentoCliente,
                        'tipo_documento' => $this->datosCliente['tipo_documento'] ?? 'CC',
                    ];
                    
                    $cliente = Cliente::create($datosCliente);
                }

                $clienteId = $cliente->id;
            } elseif ($this->cliente_id) {
                $cliente = Cliente::find($this->cliente_id);
                if ($cliente) {
                    $clienteId = $cliente->id;
                } else {
                    $this->cliente_id = null;
                    $clienteId = null;
                }
            }

            $venta = Venta::create([
                'cliente_id' => $clienteId,
                'total' => $this->total,
                'tipo_pago' => $this->tipo_pago,
                'estado' => 'Pagado',
            ]);

            foreach ($this->carrito as $item) {
                $precioOriginal = $item['precio_original'];
                $precioModificado = $item['precio_modificado'];
                $descuentoAplicado = $precioOriginal - $precioModificado;
                $cantidadPendiente = $item['cantidad'];
                
                // Identificar el producto o variante real
                $producto = null;
                $variante = null;
                
                if (isset($item['variante_id'])) {
                    $variante = ProductVariant::find($item['variante_id']);
                    $producto = $variante->producto;
                } else {
                    $producto = Producto::find($item['id']);
                }

                // Estrategia de deducción de stock:
                // 1. Buscar en Bodega Principal
                // 2. Buscar en otras bodegas con stock
                // 3. Si falta, descontar de stock directo (o dejar negativo en Principal si se prefiere, aquí usaremos Principal como fallback)

                $bodegas = \App\Models\Bodega::orderByRaw("CASE WHEN nombre = 'Principal' THEN 0 ELSE 1 END")->get();
                
                foreach ($bodegas as $bodega) {
                    if ($cantidadPendiente <= 0) break;

                    $stockDisponible = 0;
                    
                    if ($variante) {
                        $bodegaVariante = $variante->bodegas()->where('bodega_id', $bodega->id)->first();
                        $stockDisponible = $bodegaVariante ? $bodegaVariante->pivot->stock : 0;
                    } else {
                        $bodegaProducto = $producto->bodegas()->where('bodega_id', $bodega->id)->first();
                        $stockDisponible = $bodegaProducto ? $bodegaProducto->pivot->stock : 0;
                    }

                    if ($stockDisponible > 0) {
                        $cantidadADescontar = min($cantidadPendiente, $stockDisponible);
                        
                        // Registrar detalle para esta bodega
                        $venta->detalles()->create([
                            'producto_id' => $item['id'],
                            'variante_id' => $item['variante_id'] ?? null,
                            'bodega_id' => $bodega->id,
                            'cantidad' => $cantidadADescontar,
                            'precio_unitario' => $precioModificado,
                            'precio_original' => $precioOriginal,
                            'descuento_aplicado' => $descuentoAplicado,
                            'usuario_modifico_precio_id' => ($descuentoAplicado != 0) ? auth()->id() : null,
                            'subtotal' => $cantidadADescontar * $precioModificado,
                        ]);

                        // Actualizar stock
                        if ($variante) {
                            $variante->bodegas()->updateExistingPivot($bodega->id, [
                                'stock' => $stockDisponible - $cantidadADescontar
                            ]);
                        } else {
                            $producto->bodegas()->updateExistingPivot($bodega->id, [
                                'stock' => $stockDisponible - $cantidadADescontar
                            ]);
                        }

                        $cantidadPendiente -= $cantidadADescontar;
                    }
                }

                // Si aún queda cantidad pendiente (no había stock suficiente en ninguna bodega)
                // Lo asignamos a la Bodega Principal (o NULL si no hay bodegas) y dejamos que el stock se vaya a negativo o se descuente del directo
                if ($cantidadPendiente > 0) {
                    $bodegaFallback = $bodegas->first(); // Principal por el ordenamiento
                    $bodegaIdFallback = $bodegaFallback ? $bodegaFallback->id : null;

                    $venta->detalles()->create([
                        'producto_id' => $item['id'],
                        'variante_id' => $item['variante_id'] ?? null,
                        'bodega_id' => $bodegaIdFallback,
                        'cantidad' => $cantidadPendiente,
                        'precio_unitario' => $precioModificado,
                        'precio_original' => $precioOriginal,
                        'descuento_aplicado' => $descuentoAplicado,
                        'usuario_modifico_precio_id' => ($descuentoAplicado != 0) ? auth()->id() : null,
                        'subtotal' => $cantidadPendiente * $precioModificado,
                    ]);

                    // Intentar descontar del fallback
                    if ($bodegaFallback) {
                        if ($variante) {
                            $bodegaVariante = $variante->bodegas()->where('bodega_id', $bodegaFallback->id)->first();
                            if ($bodegaVariante) {
                                $variante->bodegas()->updateExistingPivot($bodegaFallback->id, [
                                    'stock' => $bodegaVariante->pivot->stock - $cantidadPendiente
                                ]);
                            } else {
                                // Si no existe la relación, la creamos con stock negativo
                                $variante->bodegas()->attach($bodegaFallback->id, ['stock' => -$cantidadPendiente]);
                            }
                        } else {
                            $bodegaProducto = $producto->bodegas()->where('bodega_id', $bodegaFallback->id)->first();
                            if ($bodegaProducto) {
                                $producto->bodegas()->updateExistingPivot($bodegaFallback->id, [
                                    'stock' => $bodegaProducto->pivot->stock - $cantidadPendiente
                                ]);
                            } else {
                                $producto->bodegas()->attach($bodegaFallback->id, ['stock' => -$cantidadPendiente]);
                            }
                        }
                    } else {
                        // Si no hay bodegas en absoluto, descontar del stock directo
                        if ($variante) {
                            $variante->decrement('stock', $cantidadPendiente);
                        } else {
                            $producto->decrement('stock', $cantidadPendiente);
                        }
                    }
                }
            }

            $cajaAbierta = Caja::where('estado', 'Abierta')
                ->orderBy('fecha_apertura', 'desc')
                ->first();

            if ($cajaAbierta) {
                MovimientoCaja::create([
                    'caja_id' => $cajaAbierta->id,
                    'tipo' => 'Ingreso',
                    'monto' => $this->total,
                    'descripcion' => 'Venta realizada. Venta ID: ' . $venta->id,
                ]);
            }

            DB::commit();
            
            $this->resetVentaState();
            
            session()->flash('message', 'Venta realizada con éxito.');
            $this->js("window.dispatchEvent(new CustomEvent('imprimir-recibo', { detail: { venta_id: {$venta->id} } }));");

        } catch (\Exception $e) {
            DB::rollBack();
            $this->resetVentaState();
            session()->flash('error', 'Error al procesar la venta. ' . $e->getMessage());
        }
    }
    
    /**
     * Resetea el estado de la venta para evitar inconsistencias
     */
    private function resetVentaState()
    {
        $this->carrito = [];
        $this->total = 0;
        $this->numeroDocumentoCliente = '';
        $this->datosCliente = [
            'nombre' => null,
            'correo' => null,
            'telefono' => null,
        ];
        $this->cliente_id = null;
        $this->tipo_pago = 'Efectivo';
        
        // Mantener la bodega seleccionada para la próxima venta
        // $this->bodega_id se mantiene
    }




    public function buscarProductoPorBarcode()
    {
        $barcode = trim($this->barcodeBusqueda);

        $producto = Producto::where('codigo_barras', $barcode)->first();
        $tipo = 'p';


        if (!$producto) {
            $producto = ProductVariant::where('barcode', $barcode)->first();
            $tipo = 'v';
        }

        if ($producto) {
            $this->agregarAlCarrito($producto->id, $tipo);
            $this->barcodeBusqueda = '';
        } else {
            session()->flash('error', 'Producto no encontrado.');
        }
    }

    public function incrementarCantidad($key)
    {
        if (isset($this->carrito[$key])) {
            $this->carrito[$key]['cantidad']++;
            $this->calcularTotal();
        }
    }

    public function decrementarCantidad($key)
    {
        if (isset($this->carrito[$key])) {
            $this->carrito[$key]['cantidad']--;

            if ($this->carrito[$key]['cantidad'] <= 0) {
                unset($this->carrito[$key]);
            }

            $this->calcularTotal();
        }
    }

    public function eliminarDelCarrito($key)
    {
        if (isset($this->carrito[$key])) {
            unset($this->carrito[$key]);
            $this->calcularTotal();
        }
    }
    public function enviarCotizacion()
    {
        $correo = $this->correoCotizacion;

        if (!filter_var($correo, FILTER_VALIDATE_EMAIL)) {
            session()->flash('error', 'Correo inválido.');
            return;
        }

        try {
            $carrito = $this->carrito;
            $total = $this->total;

            Mail::send('emails.cotizacion', compact('carrito', 'total'), function ($message) use ($correo) {
                $message->to($correo)
                    ->subject('Cotización de productos');
            });

            session()->flash('message', 'Cotización enviada exitosamente.');
            $this->correoCotizacion = '';
        } catch (\Exception $e) {
            session()->flash('error', 'Error al enviar la cotización: ' . $e->getMessage());
        }
    }

    public function buscarClientePorDocumento()
    {
        $documento = trim($this->numeroDocumentoCliente);

        if (!$documento) {
            // No se requiere documento
            $this->cliente_id = null;
            $this->datosCliente = [
                'nombre' => null,
                'correo' => null,
                'telefono' => null,
            ];
            return;
        }

        $cliente = Cliente::where('numero_documento', $documento)->first();

        if ($cliente) {
            // Verificar que el cliente encontrado existe realmente
            $clienteValidado = Cliente::find($cliente->id);
            if ($clienteValidado) {
                $this->cliente_id = $clienteValidado->id;
                $this->datosCliente = [
                    'nombre' => $clienteValidado->nombre,
                    'correo' => $clienteValidado->correo,
                    'telefono' => $clienteValidado->telefono,
                ];
            } else {
                // Cliente no válido, resetear
                $this->cliente_id = null;
                $this->datosCliente = [
                    'nombre' => null,
                    'correo' => null,
                    'telefono' => null,
                ];
            }
        } else {
            $this->cliente_id = null;
            $this->datosCliente = [
                'nombre' => null,
                'correo' => null,
                'telefono' => null,
            ];
        }
    }

    public function cambiarBodega($bodegaId)
    {
        $this->bodega_id = $bodegaId;
        
        // Opcional: mostrar notificación de cambio
        session()->flash('message', 'Bodega cambiada. Las ventas se realizarán desde la nueva bodega seleccionada.');
    }

    public function getBodegasProperty()
    {
        return \App\Models\Bodega::all();
    }


}
