<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Services\CartService;
use App\Services\OrderService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

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

    public function createOrder(Request $request): JsonResponse
    {
        $request->validate([
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'required|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',
            '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|integer|min:0',
            'guest_email' => 'required_without:user|email|nullable',
            'notes' => 'nullable|string|max:500',
        ]);

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

        $this->cartService->clear();

        return response()->json([
            'order' => [
                'id' => $order->id,
                'order_number' => $order->order_number,
                'total' => $order->total,
                'status' => $order->status,
            ],
            'message' => 'Order created. Proceed to payment.',
        ], 201);
    }

    public function getOrder(Request $request, string $orderNumber): JsonResponse
    {
        $order = Order::with(['items.product.primaryImage', 'shippingAddress', 'billingAddress', 'loyaltyTransactions'])
            ->where('order_number', $orderNumber)
            ->where(function ($q) use ($request) {
                if ($request->user()) {
                    $q->where('user_id', $request->user()->id);
                } else {
                    $q->where('guest_email', $request->query('email'));
                }
            })
            ->firstOrFail();

        $data = $order->toArray();
        $data['items'] = $order->items->map(fn($item) => [
            'id'           => $item->id,
            'product_name' => $item->product_name,
            'variant_name' => $item->variant_name,
            'sku'          => $item->sku,
            'quantity'     => $item->quantity,
            'unit_price'   => (float) $item->unit_price,
            'total_price'  => (float) $item->total_price,
            'is_preorder'  => $item->is_preorder,
            'preorder_estimated_days' => $item->preorder_estimated_days,
            'image_url'    => $item->product?->primaryImage?->url,
            'product_slug' => $item->product?->slug,
        ]);

        $data['loyalty_points_earned'] = $order->loyaltyTransactions
            ->where('type', 'earn')->sum('points');

        return response()->json(['data' => $data]);
    }

    public function shippingRates(Request $request): JsonResponse
    {
        $request->validate(['postcode' => 'required|string', 'weight_grams' => 'required|integer']);

        // Royal Mail rates — will be replaced with live API in Phase 7
        $rates = [
            [
                'id' => 'tracked_48',
                'name' => 'Royal Mail Tracked 48',
                'description' => '2–3 working days',
                'price' => 3.99,
                'estimated_days' => 3,
            ],
            [
                'id' => 'tracked_24',
                'name' => 'Royal Mail Tracked 24',
                'description' => '1–2 working days',
                'price' => 4.99,
                'estimated_days' => 2,
            ],
            [
                'id' => 'special_delivery',
                'name' => 'Royal Mail Special Delivery',
                'description' => 'Guaranteed next day before 1pm',
                'price' => 7.99,
                'estimated_days' => 1,
            ],
        ];

        // Free shipping over £75
        $subtotal = (float) $request->query('subtotal', 0);
        if ($subtotal >= 75) {
            $rates[0]['price'] = 0;
            $rates[0]['name'] .= ' (FREE)';
        }

        return response()->json(['data' => $rates]);
    }

    /**
     * GET /checkout/address-lookup?postcode=BH25ST
     *
     * Returns full addresses for a UK postcode via getAddress.io.
     * Requires `getaddress_api_key` in store settings; returns an empty
     * list when not configured so the frontend simply skips autofill.
     */
    public function addressLookup(Request $request): JsonResponse
    {
        $request->validate(['postcode' => 'required|string|max:10']);

        $apiKey = \Illuminate\Support\Facades\DB::table('store_settings')
            ->where('key', 'getaddress_api_key')->value('value');

        if (!$apiKey) {
            return response()->json(['configured' => false, 'addresses' => []]);
        }

        $clean = strtoupper(preg_replace('/\s+/', '', $request->query('postcode')));

        try {
            $res = \Illuminate\Support\Facades\Http::timeout(8)
                ->get("https://api.getaddress.io/find/{$clean}", [
                    'api-key' => $apiKey,
                    'expand'  => 'true',
                ]);

            if (!$res->successful()) {
                return response()->json(['configured' => true, 'addresses' => []]);
            }

            $data = $res->json();
            $addresses = collect($data['addresses'] ?? [])->map(function ($a) {
                $line1 = trim(implode(' ', array_filter([
                    $a['sub_building_name'] ?? '',
                    $a['building_name'] ?? '',
                    $a['building_number'] ?? '',
                    $a['thoroughfare'] ?? '',
                ])));
                $line2 = trim($a['line_2'] ?? '');
                // If line_2 duplicates line1 parts, drop it
                if ($line2 !== '' && str_contains($line1, $line2)) $line2 = '';

                return [
                    'label'          => trim(implode(', ', array_filter($a['formatted_address'] ?? []))),
                    'address_line_1' => $line1 !== '' ? $line1 : ($a['line_1'] ?? ''),
                    'address_line_2' => $line2,
                    'city'           => $a['town_or_city'] ?? '',
                    'county'         => $a['county'] ?? '',
                ];
            })->values();

            return response()->json([
                'configured' => true,
                'postcode'   => $data['postcode'] ?? $clean,
                'addresses'  => $addresses,
            ]);
        } catch (\Throwable) {
            return response()->json(['configured' => true, 'addresses' => []]);
        }
    }
}
