<?php

namespace App\Http\Controllers;

use App\Models\Cliente;
use App\Models\Comprobante;
use App\Models\Configuracion;
use App\Models\MovimientoCaja;
use App\Models\Repuesto;
use App\Models\Servicio;
use App\Models\Venta;
use App\Models\VentaDetalle;
use App\Services\Sri\Facturador;
use App\Services\Sri\SriException;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class PosController extends Controller
{
    public function index()
    {
        $clientesRecientes = Cliente::where('activo', true)->latest()->take(20)->get();
        $config = Configuracion::actual();

        return view('modulos.pos', compact('clientesRecientes', 'config'));
    }

    /** Búsqueda en vivo (AJAX) de repuestos y servicios para agregar al carrito. */
    public function buscarItems(Request $request)
    {
        $q = trim((string) $request->get('q', ''));

        $repuestos = Repuesto::where('activo', true)
            ->when($q, fn ($query) => $query->where('nombre', 'like', "%{$q}%")->orWhere('codigo', 'like', "%{$q}%"))
            ->orderBy('nombre')->limit(12)->get()
            ->map(fn ($r) => [
                'tipo' => 'repuesto',
                'item_id' => $r->id,
                'codigo' => $r->codigo,
                'descripcion' => $r->nombre,
                'precio' => (float) $r->precio_venta,
                'stock' => $r->stock,
            ]);

        $servicios = Servicio::where('activo', true)
            ->when($q, fn ($query) => $query->where('nombre', 'like', "%{$q}%")->orWhere('codigo', 'like', "%{$q}%"))
            ->orderBy('nombre')->limit(12)->get()
            ->map(fn ($s) => [
                'tipo' => 'servicio',
                'item_id' => $s->id,
                'codigo' => $s->codigo,
                'descripcion' => $s->nombre,
                'precio' => (float) $s->precio,
                'stock' => null,
            ]);

        return response()->json([
            'repuestos' => $repuestos,
            'servicios' => $servicios,
        ]);
    }

    /** Busca (o valida) un cliente por documento, para autocompletar el carrito. */
    public function buscarCliente(Request $request)
    {
        $doc = trim((string) $request->get('documento', ''));
        $cliente = Cliente::where('documento', $doc)->first();

        return response()->json(['cliente' => $cliente]);
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'cliente_id' => 'nullable|exists:clientes,id',
            'metodo_pago' => 'required|string|max:30',
            'emitir_electronico' => 'nullable|boolean',
            'tipo_identificacion' => 'nullable|string|max:2',
            'items' => 'required|array|min:1',
            'items.*.tipo' => 'required|in:repuesto,servicio',
            'items.*.item_id' => 'nullable|integer',
            'items.*.codigo' => 'nullable|string|max:40',
            'items.*.descripcion' => 'required|string|max:200',
            'items.*.cantidad' => 'required|numeric|min:0.001',
            'items.*.precio_unitario' => 'required|numeric|min:0',
            'items.*.descuento' => 'nullable|numeric|min:0',
            'items.*.porcentaje_iva' => 'required|numeric|min:0|max:100',
        ], [
            'items.required' => 'Agrega al menos un repuesto o servicio al carrito.',
        ]);

        // Validar stock disponible antes de confirmar la venta.
        foreach ($data['items'] as $item) {
            if ($item['tipo'] === 'repuesto' && ! empty($item['item_id'])) {
                $repuesto = Repuesto::find($item['item_id']);
                if ($repuesto && $repuesto->stock < $item['cantidad']) {
                    return back()->withInput()->withErrors([
                        'items' => "Stock insuficiente de \"{$repuesto->nombre}\" (disponible: {$repuesto->stock}).",
                    ]);
                }
            }
        }

        $config = Configuracion::actual();

        $venta = DB::transaction(function () use ($data, $config) {
            $subtotal0 = 0;
            $subtotal15 = 0;
            $ivaTotal = 0;
            $descuentoTotal = 0;

            $venta = Venta::create([
                'numero' => Venta::siguienteNumero(),
                'cliente_id' => $data['cliente_id'] ?? null,
                'user_id' => auth()->id(),
                'fecha' => now()->toDateString(),
                'metodo_pago' => $data['metodo_pago'],
                'estado' => 'cobrada',
            ]);

            foreach ($data['items'] as $item) {
                $cantidad = (float) $item['cantidad'];
                $precio = (float) $item['precio_unitario'];
                $descuento = (float) ($item['descuento'] ?? 0);
                $tarifa = (float) $item['porcentaje_iva'];

                $base = round(($cantidad * $precio) - $descuento, 2);
                $iva = round($base * $tarifa / 100, 2);

                VentaDetalle::create([
                    'venta_id' => $venta->id,
                    'tipo' => $item['tipo'],
                    'item_id' => $item['item_id'] ?? null,
                    'codigo' => $item['codigo'] ?? null,
                    'descripcion' => $item['descripcion'],
                    'cantidad' => $cantidad,
                    'precio_unitario' => $precio,
                    'descuento' => $descuento,
                    'porcentaje_iva' => $tarifa,
                    'subtotal' => $base,
                    'iva' => $iva,
                    'total' => $base + $iva,
                ]);

                if ($tarifa > 0) {
                    $subtotal15 += $base;
                } else {
                    $subtotal0 += $base;
                }
                $ivaTotal += $iva;
                $descuentoTotal += $descuento;

                // Descuento de stock si es un repuesto real del catálogo.
                if ($item['tipo'] === 'repuesto' && ! empty($item['item_id'])) {
                    Repuesto::where('id', $item['item_id'])->decrement('stock', $cantidad);
                }
            }

            $total = round($subtotal0 + $subtotal15 + $ivaTotal, 2);

            $venta->update([
                'subtotal_0' => $subtotal0,
                'subtotal_15' => $subtotal15,
                'descuento' => $descuentoTotal,
                'iva' => $ivaTotal,
                'total' => $total,
            ]);

            // --- Comprobante asociado a la venta ---
            $cliente = $venta->cliente_id ? Cliente::find($venta->cliente_id) : null;
            $serie = $config->serie_factura ?: 'F001';
            $ultimo = Comprobante::where('serie', $serie)->max(DB::raw('CAST(numero AS UNSIGNED)')) ?? 0;

            $comprobante = Comprobante::create([
                'tipo' => 'factura',
                'serie' => $serie,
                'numero' => $ultimo + 1,
                'venta_id' => $venta->id,
                'cliente_id' => $venta->cliente_id,
                'user_id' => auth()->id(),
                'fecha' => now()->toDateString(),
                'subtotal' => $subtotal0 + $subtotal15,
                'igv' => $ivaTotal,
                'total' => $total,
                'metodo_pago' => $data['metodo_pago'],
                'estado' => 'emitido',
                'estado_sri' => 'no_electronico',
                'tipo_identificacion_comprador' => $cliente ? ($data['tipo_identificacion'] ?? '05') : '07',
                'identificacion_comprador' => $cliente->documento ?? '9999999999999',
                'razon_social_comprador' => $cliente->nombre_completo ?? 'CONSUMIDOR FINAL',
                'direccion_comprador' => $cliente->direccion ?? null,
                'email_comprador' => $cliente->email ?? null,
            ]);

            MovimientoCaja::create([
                'tipo' => 'ingreso',
                'concepto' => 'Venta POS '.$comprobante->serie_numero.' · '.$venta->numero,
                'monto' => $total,
                'fecha' => now()->toDateString(),
                'metodo_pago' => $data['metodo_pago'],
                'comprobante_id' => $comprobante->id,
                'user_id' => auth()->id(),
            ]);

            return $venta;
        });

        $comprobante = $venta->comprobante()->latest()->first();

        if ($request->boolean('emitir_electronico') && $config->sri_activo) {
            try {
                app(Facturador::class)->emitir($comprobante);
            } catch (SriException $e) {
                Log::warning('No se pudo emitir electrónicamente desde el POS: '.$e->getMessage());
                return redirect()->route('facturacion.imprimir', $comprobante)
                    ->with('ok', 'Venta registrada. La factura quedó pendiente de envío al SRI: '.$e->getMessage());
            }
        }

        return redirect()->route('facturacion.imprimir', $comprobante)->with('ok', 'Venta registrada correctamente.');
    }
}
