<?php

namespace App\Http\Controllers\Api\Customer;

use App\Http\Controllers\Controller;
use App\Models\Address;
use App\Models\Cart;
use App\Services\CheckoutService;
use App\Services\PaymentMethods;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;

class CheckoutController extends Controller
{
    public function __construct(
        private CheckoutService $checkout,
        private PaymentMethods $paymentMethods,
    ) {}

    /**
     * POST /api/customer/checkout/preview
     * Return calculated totals + per-vendor breakdown. No commit.
     * Pass address_id to get the real distance-based delivery fee; without it,
     * delivery_total is null and needs_address is true.
     */
    public function preview(Request $request): JsonResponse
    {
        $request->validate(['address_id' => 'nullable|exists:addresses,id']);

        $user    = Auth::guard('customer')->user();
        $address = $request->filled('address_id')
            ? Address::where('user_id', $user->id)->find($request->address_id)
            : null;

        $cart = $this->currentCart();
        $b    = $this->checkout->calculate($cart, $address);

        return response()->json([
            'groups' => $b['groups']->map(fn($g) => [
                'vendor' => [
                    'id'         => $g['vendor']->id,
                    'store_name' => $g['vendor']->store_name,
                    'slug'       => $g['vendor']->slug,
                    'tier'       => $g['vendor']->tier,
                ],
                'subtotal'         => $g['subtotal'],
                'commission_rate' => $g['commission_rate'],
                'vendor_earning'  => $g['vendor_earning'],
                'items_count'      => $g['items']->count(),
            ])->values(),
            'items_total'          => $b['items_total'],
            'delivery_total'       => $b['delivery_total'],        // null until address chosen
            'delivery_distance_km' => $b['delivery_distance_km'],
            'delivery_estimated'   => $b['delivery_estimated'],
            'needs_address'        => $address === null,
            'grand_total'          => $b['grand_total'],
            'cod_otp_required'     => $b['cod_otp_required'],
        ]);
    }

    /**
     * POST /api/customer/checkout/place-order
     */
    public function placeOrder(Request $request): JsonResponse
    {
        $activeKeys = $this->paymentMethods->activeKeys();

        $request->validate([
            'address_id'     => 'required|exists:addresses,id',
            'payment_method' => ['required', Rule::in($activeKeys)],
            // Wallet (manual) payments carry the customer's transaction id.
            'payment_reference' => [
                Rule::requiredIf(fn() => $this->paymentMethods->requiresReference((string) $request->input('payment_method'))),
                'nullable', 'string', 'max:60',
            ],
        ], [
            'payment_method.in'        => 'That payment method is not available right now.',
            'payment_reference.required' => 'Please enter the transaction ID (TID) of your payment.',
        ]);

        $user    = Auth::guard('customer')->user();
        $address = Address::where('user_id', $user->id)->findOrFail($request->address_id);
        $cart    = $this->currentCart();

        $order = $this->checkout->placeOrder(
            $user, $cart, $address, $request->payment_method, $request->input('payment_reference'),
        );

        return response()->json([
            'message' => 'Order placed successfully.',
            'order' => [
                'id'               => $order->id,
                'order_number'     => $order->order_number,
                'status'           => $order->status,
                'grand_total'      => (float) $order->grand_total,
                'cod_otp_required' => false,
            ],
        ], 201);
    }

    private function currentCart(): Cart
    {
        return Cart::firstOrCreate([
            'user_id' => Auth::guard('customer')->id(),
        ]);
    }
}
