<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Services\CartService;
use App\Services\OrderService;
use App\Services\PaymentService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Log;

class PaymentController extends Controller
{
    public function __construct(
        private OrderService   $orderService,
        private PaymentService $paymentService,
        private CartService    $cartService,
    ) {}

    /**
     * POST /checkout/payment/create
     *
     * Validates the order payload, creates a pending order, then initiates
     * payment through the configured gateway (or test mode if none set).
     */
    public function create(Request $request): JsonResponse
    {
        $request->validate([
            'items'                              => 'required|array|min:1',
            'items.*.product_id'                 => 'nullable|integer|exists:products,id',
            'items.*.variant_id'                 => 'nullable|integer',
            'items.*.quantity'                   => 'required|integer|min:1',
            'items.*.price'                      => 'required|numeric|min:0',
            'items.*.name'                       => 'required|string',
            'items.*.is_preorder'                => 'boolean',
            'items.*.is_gift'                    => 'boolean',
            'shipping_address.first_name'        => 'required|string|max:100',
            'shipping_address.last_name'         => 'required|string|max:100',
            'shipping_address.address_line_1'    => 'required|string|max:255',
            'shipping_address.address_line_2'    => 'nullable|string|max:255',
            'shipping_address.city'              => 'required|string|max:100',
            'shipping_address.county'            => 'nullable|string|max:100',
            'shipping_address.postcode'          => 'required|string|max:10',
            'shipping_address.country'           => 'required|string|size:2',
            'shipping_address.phone'             => 'nullable|string|max:20',
            'billing_same'                       => 'required|boolean',
            'billing_address'                    => 'required_if:billing_same,false|array',
            'shipping_cost'                      => 'required|numeric|min:0',
            'shipping_method'                    => 'required|string',
            'discount_code'                      => 'nullable|string',
            'loyalty_points_to_use'              => 'nullable|numeric|min:0',
            'guest_email'                        => [
                                                     'nullable', 'email',
                                                     \Illuminate\Validation\Rule::requiredIf(fn() => !$request->user()),
                                                 ],
            'notes'                              => 'nullable|string|max:500',
            'selected_gateway'                   => 'nullable|string|in:exactly,fenopay',
            'utm_source'                         => 'nullable|string|max:100',
            'utm_medium'                         => 'nullable|string|max:100',
            'utm_campaign'                       => 'nullable|string|max:200',
            'utm_content'                        => 'nullable|string|max:200',
            'utm_term'                           => 'nullable|string|max:200',
            'referrer_url'                       => 'nullable|string|max:500',
            'landing_page'                       => 'nullable|string|max:500',
        ]);

        $order = $this->orderService->createFromCart(
            $request->all(),
            $request->user()
        );

        $this->cartService->clear();

        $appUrl = config('app.frontend_url', env('FRONTEND_URL', 'http://localhost:3000'));

        $result = $this->paymentService->initiatePayment(
            $order,
            returnUrl: "{$appUrl}/checkout/success?order={$order->order_number}",
            cancelUrl: "{$appUrl}/checkout/cancel?order={$order->order_number}",
            selectedGateway: $request->input('selected_gateway'),
        );

        return response()->json($result, 201);
    }

    /**
     * GET /checkout/payment/verify/{sessionId}
     *
     * Called by the frontend after returning from the gateway.
     * Marks the order as paid when confirmed.
     */
    public function verify(Request $request, string $sessionId): JsonResponse
    {
        $order = Order::where('payment_reference', $sessionId)->first();

        if (!$order) {
            return response()->json(['message' => 'Order not found.'], 404);
        }

        // Restrict to owner or guest
        if ($request->user()) {
            if ($order->user_id && $order->user_id !== $request->user()->id) {
                return response()->json(['message' => 'Unauthorised.'], 403);
            }
        }

        $status = $this->paymentService->verifySession($sessionId);

        if ($status === 'paid' && $order->status === 'pending') {
            $order->update(['status' => 'paid']);
        }

        return response()->json([
            'order_number' => $order->order_number,
            'status'       => $order->status,
            'payment'      => $status,
            'total'        => $order->total,
        ]);
    }

    /**
     * POST /checkout/payment/webhook/{gateway}
     *
     * Receives asynchronous payment confirmations from the gateway.
     * This endpoint must be excluded from CSRF and auth middleware.
     */
    public function webhook(Request $request, string $gateway): Response
    {
        $rawBody  = $request->getContent();
        $payload  = $request->json()->all();
        $signature = $request->header('X-Signature')
            ?? $request->header('X-Webhook-Signature')
            ?? '';

        $orderNumber = $this->paymentService->handleWebhook($gateway, $payload, $rawBody, $signature);

        if ($orderNumber) {
            $order = Order::where('order_number', $orderNumber)->first();
            if ($order && $order->status === 'pending') {
                $order->update(['status' => 'paid']);
                Log::info("Payment confirmed via webhook for {$orderNumber}");
            }
        }

        return response('OK', 200);
    }

    /**
     * GET /checkout/payment/config
     *
     * Returns all configured/active gateways so the checkout UI can show a choice.
     */
    public function config(): JsonResponse
    {
        $gateways = $this->paymentService->activeGateways();

        return response()->json([
            'active'   => count($gateways) > 0,
            'gateway'  => count($gateways) === 1 ? $gateways[0]['id'] : 'multiple',
            'gateways' => $gateways,
        ]);
    }
}
