<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Venta;
use App\Models\Producto;
use App\Models\Carrito;
use App\Models\DetalleVenta;
use App\Models\Orden;
use Illuminate\Support\Facades\Auth;
use Barryvdh\DomPDF\Facade\Pdf;
use App\Exports\VentasExport;
use Maatwebsite\Excel\Facades\Excel;
use Illuminate\Support\Facades\DB;

class VentaController extends Controller
{
    public function index(Request $request)
    {
        $query = Venta::with(['user', 'detalles.producto'])->orderBy('created_at', 'desc');

        if ($request->filled('busqueda')) {
            $busqueda = $request->input('busqueda');
            $query->where(function ($q) use ($busqueda) {
                $q->where('id', $busqueda)
                    ->orWhereHas('user', function ($q2) use ($busqueda) {
                        $q2->where('name', 'like', '%' . $busqueda . '%');
                    });
            });
        }

        if ($request->filled('fecha_inicio')) {
            $query->whereDate('created_at', '>=', $request->input('fecha_inicio'));
        }

        if ($request->filled('fecha_fin')) {
            $query->whereDate('created_at', '<=', $request->input('fecha_fin'));
        }

        // Clonamos la consulta para obtener el total de ventas antes de la paginación
        $totalVentas = (clone $query)->sum('total');

        $ventas = $query->paginate(20)->appends($request->all());

        $fecha_inicio = $request->input('fecha_inicio', '');
        $fecha_fin = $request->input('fecha_fin', '');

        // Pasamos la variable $totalVentas a la vista
        return view('ventas.index', compact('ventas', 'fecha_inicio', 'fecha_fin', 'totalVentas'));
    }

    public function show(Venta $venta)
    {
        $venta->load(['user', 'detalles.producto']);
        $descuentos = json_decode($venta->descuentos, true);

        return view('ventas.show', compact('venta', 'descuentos'));
    }

    /**
     * Elimina una venta del historial sin devolver el stock.
     *
     * @param    \App\Models\Venta    $venta
     * @return \Illuminate\Http\RedirectResponse
     */
    public function destroy(Venta $venta)
    {
        // Verificar si el usuario es un administrador antes de proceder
        if (!Auth::check() || !Auth::user()->is_admin) {
            abort(403, 'Acceso no autorizado.');
        }

        // Envolver la lógica en una transacción de base de datos para garantizar la integridad
        return DB::transaction(function () use ($venta) {
            try {
                // Eliminar los detalles de la venta
                $venta->detalles()->delete();
                // Eliminar la venta principal
                $venta->delete();

                return redirect()->route('ventas.index')
                    ->with('success', 'Venta eliminada del historial correctamente.');
            } catch (\Exception $e) {
                // Si ocurre un error, la transacción se revertirá automáticamente
                return redirect()->route('ventas.index')
                    ->with('error', 'Error al eliminar la venta. Por favor, inténtelo de nuevo.');
            }
        });
    }

    /**
     * Actualiza la fecha de una venta.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\RedirectResponse
     */
    public function updateDate(Request $request)
    {
        // Asegurar que solo los administradores puedan acceder a esta función
        if (!Auth::check() || !Auth::user()->is_admin) {
            abort(403, 'Acceso no autorizado.');
        }

        // Validar los datos de entrada
        $request->validate([
            'venta_id' => 'required|exists:ventas,id',
            'new_date' => 'required|date',
        ]);

        return DB::transaction(function () use ($request) {
            try {
                $venta = Venta::findOrFail($request->input('venta_id'));
                $venta->created_at = $request->input('new_date');
                $venta->save();

                return redirect()->route('ventas.index')
                    ->with('success', 'La fecha de la venta ha sido actualizada correctamente.');
            } catch (\Exception $e) {
                return redirect()->route('ventas.index')
                    ->with('error', 'Error al actualizar la fecha de la venta. Por favor, inténtelo de nuevo.');
            }
        });
    }

    /**
     * Procesa la devolución de productos de una venta.
     *
     * @param    \Illuminate\Http\Request  $request
     * @param    \App\Models\Venta    $venta
     * @return \Illuminate\Http\RedirectResponse
     */
    public function devolver(Request $request, Venta $venta)
    {
        // La ruta está protegida por el middleware 'auth', así que
        // no se necesita una verificación adicional aquí. Cualquier usuario
        // autenticado (incluidos los vendedores) puede realizar devoluciones.

        $request->validate([
            'detalle_id' => 'required|exists:detalle_ventas,id',
            'cantidad_devolver' => 'required|integer|min:1',
        ]);

        return DB::transaction(function () use ($request, $venta) {
            try {
                $detalleId = $request->input('detalle_id');
                $cantidadADevolver = $request->input('cantidad_devolver');

                $detalle = DetalleVenta::findOrFail($detalleId);
                $producto = Producto::find($detalle->producto_id);

                if (!$producto) {
                    throw new \Exception('Producto no encontrado.');
                }

                // Validar que la cantidad a devolver no sea mayor a la vendida
                if ($cantidadADevolver > $detalle->cantidad) {
                    return redirect()->back()
                        ->with('error', 'La cantidad a devolver no puede ser mayor que la cantidad vendida.');
                }

                // Calcular el monto a devolver basado en el precio unitario y el descuento
                $precioUnitario = $detalle->precio;
                $cantidadVendida = $detalle->cantidad;
                $descuentoTotalDetalle = $detalle->descuento;

                // Precio unitario con el descuento prorrateado
                $precioUnitarioConDescuento = ($precioUnitario * $cantidadVendida - $descuentoTotalDetalle) / $cantidadVendida;
                $montoADevolver = $cantidadADevolver * $precioUnitarioConDescuento;

                // Actualizar el stock del producto
                $producto->cantidad += $cantidadADevolver;
                $producto->save();

                // Actualizar la cantidad del detalle de la venta
                $detalle->cantidad -= $cantidadADevolver;
                $detalle->descuento -= ($descuentoTotalDetalle / $cantidadVendida) * $cantidadADevolver;
                $detalle->save();

                // Actualizar el total de la venta principal
                $venta->total -= $montoADevolver;
                $venta->save();

                // Si el detalle de la venta llega a 0, lo eliminamos
                if ($detalle->cantidad <= 0) {
                    $detalle->delete();
                }

                return redirect()->back()->with('success', 'Devolución procesada correctamente. Se han devuelto $' . number_format($montoADevolver, 2) . ' y se ha actualizado el stock.');

            } catch (\Exception $e) {
                return redirect()->back()->with('error', 'Error al procesar la devolución: ' . $e->getMessage());
            }
        });
    }

    public function confirmar(Request $request)
    {
        $userId = Auth::id();
        $carrito = Carrito::with('producto')->where('user_id', $userId)->get();

        if ($carrito->isEmpty()) {
            return redirect()->route('carrito.index')->with('error', 'El carrito está vacío.');
        }

        foreach ($carrito as $item) {
            if ($item->cantidad > $item->producto->cantidad) {
                return redirect()->route('carrito.index')
                    ->with('error', 'No hay suficiente stock para: ' . $item->producto->nombre);
            }
        }

        $descuentosProducto = $request->input('descuento_producto', []);
        $tiposDescuentoProducto = $request->input('tipo_descuento_producto', []);
        $descuentoGeneral = $request->input('descuento_general', 0);
        $tipoDescuentoGeneral = $request->input('tipo_descuento_general', 'fijo');

        $descuentosProductoPorId = [];
        $tiposDescuentoProductoPorId = [];

        foreach ($carrito as $item) {
            $prodId = $item->producto->id;
            $descuentosProductoPorId[$prodId] = $descuentosProducto[$prodId] ?? 0;
            $tiposDescuentoProductoPorId[$prodId] = $tiposDescuentoProducto[$prodId] ?? 'fijo';
        }

        $totales = $this->calcularTotalesConDescuento(
            $carrito,
            $descuentosProductoPorId,
            $tiposDescuentoProductoPorId,
            $descuentoGeneral,
            $tipoDescuentoGeneral
        );

        $total = $totales['total'];
        $totalConDescuento = $totales['totalConDescuento'];

        $descuentos = [
            'productos' => $totales['descuentosProducto'],
            'general' => [
                'monto' => $totales['descuentoGeneral'],
                'tipo' => $totales['tipoDescuentoGeneral'],
            ],
        ];

        return view('ventas.confirmar', compact('carrito', 'total', 'totalConDescuento', 'descuentos'));
    }

    public function procesar(Request $request)
    {
        //dd($request->all());
        $userId = Auth::id();
        $carrito = Carrito::with('producto')->where('user_id', $userId)->get();

        if ($carrito->isEmpty()) {
            return redirect()->route('carrito.index')->with('error', 'El carrito está vacío.');
        }

        foreach ($carrito as $item) {
            if ($item->cantidad > $item->producto->cantidad) {
                return redirect()->route('carrito.index')
                    ->with('error', 'No hay suficiente stock para: ' . $item->producto->nombre);
            }
        }

        // Recoger descuentos individuales
        $descuentosProducto = [];
        $tiposDescuentoProducto = [];

        foreach ($carrito as $item) {
            $prodId = $item->producto->id;
            $descuento = floatval($request->input("descuento_producto.$prodId", 0));
            $tipo = $request->input("tipo_descuento_producto.$prodId", 'fijo');

            $subtotal = $item->producto->precio * $item->cantidad;
            if ($tipo === 'porcentaje' && $descuento > 100) {
                $descuento = 100;
            } elseif ($tipo === 'fijo' && $descuento > $subtotal) {
                $descuento = $subtotal;
            }

            $descuentosProducto[$prodId] = $descuento;
            $tiposDescuentoProducto[$prodId] = $tipo;
        }

        $descuentoGeneral = floatval($request->input('descuento_general', 0));
        $tipoDescuentoGeneral = $request->input('tipo_descuento_general', 'fijo');
        $totalFinalConfirmado = floatval($request->input('total_con_descuento', 0));

        // Calcular totales y descuentos
        $totales = $this->calcularTotalesConDescuento(
            $carrito,
            $descuentosProducto,
            $tiposDescuentoProducto,
            $descuentoGeneral,
            $tipoDescuentoGeneral
        );

        $venta = Venta::create([
            'user_id' => $userId,
            'fecha' => now(),
            'total' => $totalFinalConfirmado,
            'descuentos' => json_encode([
                'productos' => $totales['descuentosProducto'],
                'general' => [
                    'monto' => $totales['descuentoGeneral'],
                    'tipo' => $tipoDescuentoGeneral
                ]
            ])
        ]);

        foreach ($carrito as $item) {
            $producto = $item->producto;
            $prodId = $producto->id;

            $subtotal = $producto->precio * $item->cantidad;
            $descuento = $totales['descuentosProducto'][$prodId]['monto'] ?? 0;

            $producto->cantidad -= $item->cantidad;
            $producto->save();

            DetalleVenta::create([
                'venta_id' => $venta->id,
                'producto_id' => $prodId,
                'cantidad' => $item->cantidad,
                'precio' => $producto->precio,
                'subtotal' => $subtotal,
                'descuento' => $descuento,
                'total_final' => $totalFinalConfirmado,
                'metodo_pago' => $request->input('metodo_pago'), // <-- ¡AQUÍ!
            ]);

            $this->verificarOrdenReposicion($producto);
        }

        Carrito::where('user_id', $userId)->delete();

        return redirect()->route('ventas.show', $venta->id)
            ->with('success', 'Venta procesada correctamente');
    }

    private function calcularTotalesConDescuento($carrito, $descuentosProducto, $tiposDescuentoProducto, $descuentoGeneral, $tipoDescuentoGeneral)
    {
        $total = 0;
        $descuentos = [];

        foreach ($carrito as $item) {
            $prodId = $item->producto->id;
            $subtotal = $item->producto->precio * $item->cantidad;
            $descuento = $descuentosProducto[$prodId] ?? 0;
            $tipo = $tiposDescuentoProducto[$prodId] ?? 'fijo';

            $descuentoAplicado = $tipo === 'porcentaje'
                ? $subtotal * ($descuento / 100)
                : $descuento;

            $totalProducto = max($subtotal - $descuentoAplicado, 0);
            $total += $totalProducto;

            $descuentos[$prodId] = [
                'monto' => $descuentoAplicado,
                'tipo' => $tipo,
                'subtotal' => $subtotal,
                'total' => $totalProducto,
            ];
        }

        $descuentoGeneralAplicado = $tipoDescuentoGeneral === 'porcentaje'
            ? $total * ($descuentoGeneral / 100)
            : $descuentoGeneral;

        $totalConDescuento = max($total - $descuentoGeneralAplicado, 0);

        return [
            'total' => $total,
            'totalConDescuento' => $totalConDescuento,
            'descuentoGeneral' => $descuentoGeneralAplicado,
            'descuentosProducto' => $descuentos,
            'tipoDescuentoGeneral' => $tipoDescuentoGeneral
        ];
    }

    private function verificarOrdenReposicion($producto)
    {
        if ($producto->cantidad <= $producto->minimo) {
            $cantidadOrden = $producto->maximo - $producto->cantidad;

            Orden::firstOrCreate(
                ['producto_id' => $producto->id, 'estado' => 'pendiente'],
                [
                    'nombre' => $producto->nombre,
                    'codigo' => $producto->codigo,
                    'precio' => $producto->precio,
                    'cantidad' => $cantidadOrden,
                    'minimo' => $producto->minimo,
                    'maximo' => $producto->maximo,
                    'descripcion' => $producto->descripcion,
                    'imagen' => $producto->imagen,
                    'estado' => 'pendiente'
                ]
            );
        }
    }
    public function exportarPdf(Request $request)
    {
        $query = Venta::with(['user', 'detalles.producto'])->orderBy('created_at', 'desc');

        if ($request->filled('busqueda')) {
            $busqueda = $request->input('busqueda');
            $query->where(function ($q) use ($busqueda) {
                $q->where('id', $busqueda)
                    ->orWhereHas('user', function ($q2) use ($busqueda) {
                        $q2->where('name', 'like', '%' . $busqueda . '%');
                    });
            });
        }

        if ($request->filled('fecha_inicio')) {
            $query->whereDate('created_at', '>=', $request->input('fecha_inicio'));
        }

        if ($request->filled('fecha_fin')) {
            $query->whereDate('created_at', '<=', $request->input('fecha_fin'));
        }

        $ventas = $query->get();

        // Puedes pasar también los filtros si los necesitas mostrar en el PDF
        $fecha_inicio = $request->input('fecha_inicio', '');
        $fecha_fin = $request->input('fecha_fin', '');

        $pdf = Pdf::loadView('ventas.pdf', compact('ventas', 'fecha_inicio', 'fecha_fin'))
            ->setPaper('a4', 'portrait'); // o 'landscape' si quieres horizontal

        return $pdf->download('historial_ventas.pdf');
    }
    public function exportarExcel(Request $request)
    {
        $busqueda = $request->input('busqueda');
        $fecha_inicio = $request->input('fecha_inicio');
        $fecha_fin = $request->input('fecha_fin');

        return Excel::download(
            new VentasExport($busqueda, $fecha_inicio, $fecha_fin),
            'historial_ventas.xlsx'
        );
    }
}
