<?php

namespace App\Http\Controllers;

use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Setting;
use App\Payments\PaymentGatewayInterface;
use App\Services\SunatService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

/**
 * Checkout con desglose contable para Perú (SUNAT):
 *   - Subtotal de productos (base imponible sin IGV)
 *   - Handling fee (empaque) + Delivery fee (envío, gratis sobre umbral)
 *   - IGV 18% trasladado al cliente
 *   - Provisión de Impuesto a la Renta 2% sobre la base imponible
 *
 * La pasarela de pago se inyecta vía PaymentGatewayInterface (patrón Strategy).
 */
class CheckoutController extends Controller
{
    // Tasas fijas de negocio.
    private const IGV_RATE   = 0.18; // 18%
    private const RENTA_RATE = 0.02; // 2% provisión I. Renta

    public function __construct(
        private PaymentGatewayInterface $gateway,
        private SunatService $sunat,
    ) {}

    public function index()
    {
        $cart = session()->get('cart', []);
        if (count($cart) === 0) {
            return redirect()->route('cart.index');
        }

        $breakdown = $this->calculate($cart);
        return view('store.checkout', array_merge(['cart' => $cart], $breakdown));
    }

    public function process(Request $request)
    {
        $request->validate([
            'customer_name'       => 'required|string|max:150',
            'customer_email'      => 'required|email',
            'customer_doc_type'   => 'required|in:1,6', // 1=DNI, 6=RUC
            'customer_doc_number' => 'required|string|max:15',
            'shipping_address'    => 'required|string|max:255',
        ]);

        $cart = session()->get('cart', []);
        if (count($cart) === 0) {
            return redirect()->route('cart.index');
        }

        $b = $this->calculate($cart);

        // Crear pedido + items dentro de una transacción.
        $order = DB::transaction(function () use ($request, $cart, $b) {
            $order = Order::create([
                'order_number'        => 'ORD-' . strtoupper(uniqid()),
                'customer_name'       => $request->customer_name,
                'customer_email'      => $request->customer_email,
                'customer_doc_type'   => $request->customer_doc_type,
                'customer_doc_number' => $request->customer_doc_number,
                'shipping_address'    => $request->shipping_address,
                'subtotal'            => $b['base_imponible'],
                'igv'                 => $b['igv'],
                'handling_fee'        => $b['handling_fee'],
                'delivery_fee'        => $b['delivery_fee'],
                'total'               => $b['total'],
                'renta_provision'     => $b['renta_provision'],
                'status'              => 'pending',
                'payment_method'      => $this->gateway->name(),
            ]);

            foreach ($cart as $id => $item) {
                OrderItem::create([
                    'order_id'     => $order->id,
                    'product_id'   => $id,
                    'product_name' => $item['name'],
                    'price'        => $item['price'],
                    'quantity'     => $item['quantity'],
                ]);
            }

            return $order;
        });

        session()->put('pending_order_id', $order->id);

        // Redirigir a la pasarela (PayPal). En modo demo vuelve a success.
        $payUrl = $this->gateway->createPayment($order);
        return redirect()->away($payUrl);
    }

    public function success(Request $request)
    {
        $orderId = $request->get('order') ?? session()->get('pending_order_id');
        $order = $orderId ? Order::find($orderId) : null;

        if ($order && $order->status !== 'paid') {
            // Confirmar pago con la pasarela.
            if ($this->gateway->capturePayment($order, $request->all())) {
                $order->update(['status' => 'paid']);

                // Enviar comprobante electrónico a SUNAT (no bloquea la compra).
                try {
                    $this->sunat->emitInvoice($order);
                } catch (\Throwable $e) {
                    logger()->error('SUNAT: ' . $e->getMessage());
                }

                session()->forget(['cart', 'pending_order_id']);
            }
        }

        return view('store.checkout-success', compact('order'));
    }

    public function cancel()
    {
        return view('store.checkout-cancel');
    }

    /**
     * Núcleo del cálculo contable.
     *
     * Los fees se consideran afectos a IGV. Trabajamos "hacia atrás":
     * el total con IGV = productos + handling + delivery, y de ahí
     * separamos base imponible e IGV.
     */
    private function calculate(array $cart): array
    {
        $productsTotal = collect($cart)->sum(fn ($i) => $i['price'] * $i['quantity']);

        $handlingFee = (float) Setting::get('handling_fee', 5.00);

        // Envío gratis si supera el umbral configurable.
        $freeThreshold = (float) Setting::get('shipping_free_threshold', env('SHIPPING_FREE_THRESHOLD', 200));
        $deliveryFee   = $productsTotal >= $freeThreshold
            ? 0.00
            : (float) Setting::get('delivery_fee', 15.00);

        // Total cobrado al cliente (incluye IGV).
        $totalConIgv = round($productsTotal + $handlingFee + $deliveryFee, 2);

        // Separar base imponible e IGV.
        $baseImponible = round($totalConIgv / (1 + self::IGV_RATE), 2);
        $igv           = round($totalConIgv - $baseImponible, 2);

        // Provisión de Impuesto a la Renta (2% sobre la base imponible).
        $rentaProvision = round($baseImponible * self::RENTA_RATE, 2);

        return [
            'products_total'  => round($productsTotal, 2),
            'handling_fee'    => $handlingFee,
            'delivery_fee'    => $deliveryFee,
            'free_threshold'  => $freeThreshold,
            'base_imponible'  => $baseImponible,
            'igv'             => $igv,
            'renta_provision' => $rentaProvision,
            'total'           => $totalConIgv,
        ];
    }
}
