<?php

namespace App\Http\Controllers;

use App\Models\{CajaSesion, CajaMovimiento};
use App\Services\CajaService;
use App\Http\Requests\CajaMovimientoRequest;
use App\Http\Requests\CajaAperturaRequest;
use Illuminate\Http\Request;

class CajaController extends Controller
{
    public function __construct(private CajaService $cajaService) {}

    public function index()
    {
        $sucursalId = session('sucursal_id');
        $sesion     = CajaSesion::where('sucursal_id', $sucursalId)
                         ->abiertas()
                         ->with('movimientosActivos')
                         ->first();

        $ultimosCierres = CajaSesion::where('sucursal_id', $sucursalId)
                            ->where('estado', 'cerrada')
                            ->latest('cerrada_at')
                            ->take(5)
                            ->get();

        return view('caja.index', compact('sesion', 'ultimosCierres'));
    }

    public function abrir(CajaAperturaRequest $request)
    {

        try {
            $this->cajaService->abrirSesion(
                sucursalId:    session('sucursal_id'),
                montoApertura: $request->monto_apertura,
                userId:        auth()->id(),
            );
            return redirect()->route('caja.index')
                ->with('success', 'Caja abierta correctamente.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    public function movimiento(CajaMovimientoRequest $request)
    {
        $sucursalId = session('sucursal_id');
        $sesion     = CajaSesion::where('sucursal_id', $sucursalId)->abiertas()->firstOrFail();

        try {
            $this->cajaService->registrarMovimiento($sesion, $request->validated());
            return back()->with('success', 'Movimiento registrado.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    public function cerrar(Request $request)
    {
        $request->validate([
            'monto_cierre' => ['required', 'numeric', 'min:0'],
            'notas_cierre' => ['nullable', 'string', 'max:500'],
        ]);

        $sucursalId = session('sucursal_id');
        $sesion     = CajaSesion::where('sucursal_id', $sucursalId)->abiertas()->firstOrFail();

        $sesionCerrada = $this->cajaService->cerrarSesion(
            sesion:       $sesion,
            montoCierre:  $request->monto_cierre,
            notas:        $request->notas_cierre,
        );

        $diferencia = $sesionCerrada->diferencia;
        $msg = $diferencia == 0
            ? 'Caja cerrada. Cuadre perfecto.'
            : ($diferencia > 0
                ? "Caja cerrada. Sobrante: S/. " . number_format(abs($diferencia), 2)
                : "Caja cerrada. Faltante: S/. " . number_format(abs($diferencia), 2));

        return redirect()->route('caja.index')->with('success', $msg);
    }

    public function anular(Request $request, CajaMovimiento $mov)
    {
        $request->validate([
            'motivo_anulacion' => ['required', 'string', 'min:5', 'max:300'],
        ]);

        try {
            $this->cajaService->anularMovimiento($mov, $request->motivo_anulacion);
            return back()->with('success', 'Movimiento anulado.');
        } catch (\Exception $e) {
            return back()->withErrors(['error' => $e->getMessage()]);
        }
    }

    public function sesion(CajaSesion $sesion)
    {
        $sesion->load(['movimientos.registradoPor', 'abiertaPor', 'cerradaPor', 'sucursal']);
        return view('caja.sesion', compact('sesion'));
    }

    public function historial(Request $request)
    {
        $sucursalId = session('sucursal_id');
        $sesiones   = CajaSesion::where('sucursal_id', $sucursalId)
                        ->with(['abiertaPor', 'cerradaPor'])
                        ->when($request->desde, fn($q) => $q->whereDate('abierta_at', '>=', $request->desde))
                        ->when($request->hasta, fn($q) => $q->whereDate('abierta_at', '<=', $request->hasta))
                        ->latest('abierta_at')
                        ->paginate(20)
                        ->withQueryString();

        return view('caja.historial', compact('sesiones'));
    }

    public function exportar(CajaSesion $sesion)
    {
        $sesion->load(['movimientos.registradoPor', 'sucursal']);

        return response()->streamDownload(function () use ($sesion) {
            $h = fopen('php://output', 'w');
            fputcsv($h, ['GastroGe — Resumen de Caja']);
            fputcsv($h, ['Sucursal', $sesion->sucursal->nombre]);
            fputcsv($h, ['Apertura', $sesion->abierta_at->format('d/m/Y H:i')]);
            fputcsv($h, ['Apertura S/.', $sesion->monto_apertura]);
            fputcsv($h, []);
            fputcsv($h, ['Hora', 'Tipo', 'Concepto', 'Categoría', 'Monto', 'Comprobante', 'Usuario', 'Anulado']);
            foreach ($sesion->movimientos as $m) {
                fputcsv($h, [
                    $m->created_at->format('H:i'),
                    strtoupper($m->tipo),
                    $m->concepto,
                    $m->categoria,
                    $m->monto,
                    $m->comprobante_numero ?? '—',
                    $m->registradoPor->name ?? '—',
                    $m->anulado ? 'SÍ' : 'NO',
                ]);
            }
            fputcsv($h, []);
            fputcsv($h, ['Total Ingresos', $sesion->total_ingresos]);
            fputcsv($h, ['Total Egresos',  $sesion->total_egresos]);
            fputcsv($h, ['Diferencia',     $sesion->diferencia]);
            fclose($h);
        }, "caja_{$sesion->id}_{$sesion->abierta_at->format('Ymd')}.csv", ['Content-Type' => 'text/csv']);
    }
}