<?php

namespace App\Http\Controllers;

use App\Models\Comprobante;
use App\Models\Configuracion;
use App\Models\MovimientoCaja;
use App\Models\Orden;
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 FacturacionController extends Controller
{
    public function index(Request $request)
    {
        $q = trim($request->get('q', ''));

        $comprobantes = Comprobante::with(['cliente', 'orden'])
            ->when($q, fn ($query) => $query->where('numero', 'like', "%{$q}%")
                ->orWhere('serie', 'like', "%{$q}%")
                ->orWhereHas('cliente', fn ($c) => $c->where('nombre', 'like', "%{$q}%")))
            ->latest()->paginate(12)->withQueryString();

        $resumen = [
            'emitidos' => Comprobante::where('estado', 'emitido')->count(),
            'ventas_mes' => Comprobante::where('estado', 'emitido')->whereMonth('fecha', now()->month)->whereYear('fecha', now()->year)->sum('total'),
            'ticket' => round((float) Comprobante::where('estado', 'emitido')->avg('total'), 2),
        ];

        return view('modulos.facturacion', compact('comprobantes', 'resumen', 'q'));
    }

    public function create()
    {
        // Órdenes facturables: con total > 0 y sin comprobante emitido
        $facturadas = Comprobante::where('estado', 'emitido')->whereNotNull('orden_id')->pluck('orden_id');

        $ordenes = Orden::with(['cliente', 'vehiculo'])
            ->where('total', '>', 0)
            ->whereNotIn('estado', ['anulado'])
            ->whereNotIn('id', $facturadas)
            ->latest()->get();

        return view('modulos.facturacion_form', compact('ordenes'));
    }

    public function store(Request $request)
    {
        $data = $request->validate([
            'orden_id' => 'required|exists:ordenes,id',
            'tipo' => 'required|in:boleta,factura',
            'metodo_pago' => 'required|string|max:30',
            'tipo_identificacion' => 'nullable|string|max:2',
            'emitir_electronico' => 'nullable|boolean',
        ], [
            'orden_id.required' => 'Selecciona la orden a facturar.',
        ]);

        $comprobante = DB::transaction(function () use ($data) {
            $orden = Orden::with('cliente')->findOrFail($data['orden_id']);
            $config = Configuracion::actual();
            $serie = $data['tipo'] === 'factura' ? $config->serie_factura : $config->serie_boleta;

            $ultimo = Comprobante::where('serie', $serie)->max(DB::raw('CAST(numero AS UNSIGNED)')) ?? 0;
            $cliente = $orden->cliente;

            $comprobante = Comprobante::create([
                'tipo' => $data['tipo'],
                'serie' => $serie,
                'numero' => $ultimo + 1,
                'orden_id' => $orden->id,
                'cliente_id' => $orden->cliente_id,
                'user_id' => auth()->id(),
                'fecha' => now()->toDateString(),
                'subtotal' => $orden->subtotal - $orden->descuento,
                'igv' => $orden->impuesto,
                'total' => $orden->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,
            ]);

            // Marcar la orden como pagada
            $orden->update(['estado_pago' => 'pagado']);

            // Ingreso en caja
            MovimientoCaja::create([
                'tipo' => 'ingreso',
                'concepto' => 'Venta '.$comprobante->serie_numero.' · Orden '.$orden->numero,
                'monto' => $orden->total,
                'fecha' => now()->toDateString(),
                'metodo_pago' => $data['metodo_pago'],
                'orden_id' => $orden->id,
                'comprobante_id' => $comprobante->id,
                'user_id' => auth()->id(),
            ]);

            return $comprobante;
        });

        $config = Configuracion::actual();
        if ($request->boolean('emitir_electronico') && $data['tipo'] === 'factura' && $config->sri_activo) {
            try {
                app(Facturador::class)->emitir($comprobante);
            } catch (SriException $e) {
                Log::warning('No se pudo emitir electrónicamente: '.$e->getMessage());

                return redirect()->route('facturacion.imprimir', $comprobante)
                    ->with('ok', 'Comprobante creado. Quedó pendiente de envío al SRI: '.$e->getMessage());
            }
        }

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

    public function imprimir(Comprobante $comprobante)
    {
        $comprobante->load(['cliente', 'orden.servicios', 'orden.repuestos', 'orden.vehiculo', 'venta.detalles']);
        $config = Configuracion::actual();

        return view('modulos.comprobante_print', compact('comprobante', 'config'));
    }

    public function anular(Comprobante $comprobante)
    {
        if ($comprobante->estado_sri === 'autorizado') {
            return redirect()->route('facturacion.index')->with(
                'error',
                'Este comprobante ya fue autorizado por el SRI. No se puede "anular" localmente: '
                .'la única forma válida ante el SRI es emitir una Nota de Crédito referida a esta factura (no incluida en este módulo).'
            );
        }

        if ($comprobante->estado === 'emitido') {
            DB::transaction(function () use ($comprobante) {
                $comprobante->update(['estado' => 'anulado']);

                if ($comprobante->orden_id) {
                    Orden::where('id', $comprobante->orden_id)->update(['estado_pago' => 'pendiente']);
                }

                // Egreso compensatorio en caja
                MovimientoCaja::create([
                    'tipo' => 'egreso',
                    'concepto' => 'Anulación comprobante '.$comprobante->serie_numero,
                    'monto' => $comprobante->total,
                    'fecha' => now()->toDateString(),
                    'metodo_pago' => $comprobante->metodo_pago ?? 'efectivo',
                    'comprobante_id' => $comprobante->id,
                    'user_id' => auth()->id(),
                ]);
            });
        }

        return redirect()->route('facturacion.index')->with('ok', 'Comprobante anulado.');
    }
}
