<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Payment;
use App\Models\Shipment;
use App\Models\StockHistory;
use App\Models\Product;
use App\Services\PaymentService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\Log;

class CheckoutController extends Controller
{
    protected $paymentService;

    public function __construct(PaymentService $paymentService)
    {
        $this->paymentService = $paymentService;
    }

    public function store(Request $request)
    {
        // 1. Validasi Request
        $validator = Validator::make($request->all(), [
            'payment_gateway' => 'required',
            'payment_method'  => 'required',
            'customer.name'   => 'required',
            'customer.email'  => 'required|email',
            'customer.phone'  => 'required',
            'items'           => 'required|array|min:1',
            'items.*.product_id' => 'required',
            'items.*.qty'        => 'required|integer|min:1'
        ], [
            'customer.name.required' => 'Nama wajib diisi.',
            'customer.email.required' => 'Email wajib diisi.',
            'customer.email.email' => 'Format email tidak valid.',
            'customer.phone.required' => 'Nomor HP wajib diisi.'
        ]);

        if ($validator->fails()) {
            return response()->json([
                'success' => false,
                'message' => 'Validation Error',
                'errors' => $validator->errors()
            ], 422);
        }

        // 2. Validasi & Cek Stok
        $subtotal = 0;
        $itemsToCheckout = [];
        foreach ($request->items as $item) {
            $product = Product::find($item['product_id']);
            if (!$product) {
                return response()->json([
                    'success' => false,
                    'message' => 'Produk tidak ditemukan.'
                ], 404);
            }
            if ($item['qty'] < $product->min_purchase) {
                return response()->json([
                    'success' => false,
                    'message' => "Minimal pembelian produk {$product->name} adalah {$product->min_purchase} pcs."
                ], 400);
            }
            if ($product->stock < $item['qty']) {
                return response()->json([
                    'success' => false,
                    'message' => 'Stok produk tidak mencukupi.'
                ], 400);
            }
            $subtotal += ($product->final_price * $item['qty']);
            $itemsToCheckout[] = [
                'product' => $product,
                'qty' => $item['qty']
            ];
        }

        $shippingCost = (int)$request->input('shipping_cost', 0);
        $grandTotal = $subtotal + $shippingCost;

        // 3. Idempotency Check (Kembalikan order PENDING yang sama jika ada)
        $userId = auth()->id();
        $existingOrder = Order::where('user_id', $userId)
            ->where('status', 'pending')
            ->where('total', $grandTotal)
            ->latest()
            ->first();

        if ($existingOrder) {
            $existingItemIds = $existingOrder->items->pluck('product_id')->toArray();
            $requestItemIds = collect($request->items)->pluck('product_id')->toArray();
            sort($existingItemIds);
            sort($requestItemIds);
            
            if ($existingItemIds === $requestItemIds) {
                $payment = $existingOrder->payment;
                if ($payment && $payment->payment_url) {
                    $responsePayload = [
                        'success' => true,
                        'message' => 'Checkout berhasil (Idempotency)',
                        'invoice' => $existingOrder->invoice_number,
                        'payment_gateway' => $payment->payment_gateway,
                        'gateway' => $payment->payment_gateway,
                        'payment_url' => $payment->payment_url,
                        'expired_at' => $payment->expired_at
                    ];
                    if ($payment->payment_gateway === 'midtrans') {
                        $responsePayload['token'] = $payment->token;
                    } else {
                        $responsePayload['reference'] = $payment->reference;
                    }
                    return response()->json($responsePayload);
                }
            }
        }

        // 4. Generate Invoice Unik
        $invoiceNumber = 'INV' . date('Ymd') . sprintf('%04d', Order::whereDate('created_at', today())->count() + 1);

        try {
            // 5. Database Transaction
            $order = DB::transaction(function () use ($request, $invoiceNumber, $grandTotal, $shippingCost, $itemsToCheckout, $userId) {
                // Construct shipping address
                $customer = $request->customer;
                $address = $request->shipping_address;
                $villagePart = isset($address['village']) && !empty($address['village']) ? "{$address['village']}, " : "";
                $districtPart = isset($address['district']) && !empty($address['district']) ? "{$address['district']}, " : "";
                $fullAddressText = "{$customer['name']} ({$customer['phone']}) - " . 
                                   ($address['address'] ?? '') . ", " .
                                   $villagePart .
                                   $districtPart .
                                   ($address['city'] ?? '') . ", " .
                                   ($address['province'] ?? '');

                // Simpan Order
                $order = Order::create([
                    'user_id' => $userId,
                    'invoice_number' => $invoiceNumber,
                    'status' => 'pending', // Status awal: PENDING
                    'total' => $grandTotal,
                    'shipping_cost' => $shippingCost,
                    'discount_amount' => 0,
                    'shipping_address' => $fullAddressText
                ]);

                // Simpan Detail Order & Kurangi Stok
                foreach ($itemsToCheckout as $itemData) {
                    $product = $itemData['product'];
                    $qty = $itemData['qty'];

                    OrderItem::create([
                        'order_id' => $order->id,
                        'product_id' => $product->id,
                        'qty' => $qty,
                        'price' => $product->final_price
                    ]);

                    // Kurangi stok
                    $product->decrement('stock', $qty);

                    // Catat Stock History
                    StockHistory::create([
                        'product_id' => $product->id,
                        'quantity' => -$qty,
                        'type' => 'out',
                        'description' => "Checkout Order: {$invoiceNumber}"
                    ]);
                }

                // Simpan Shipment
                Shipment::create([
                    'order_id' => $order->id,
                    'courier' => strtoupper($request->courier ?? 'jne'),
                    'service' => strtoupper($request->service ?? 'REG'),
                    'status' => 'pending'
                ]);

                return $order;
            });

            // 6. Request ke Payment Gateway
            $paymentDetails = [];
            switch ($request->payment_gateway) {
                case 'midtrans':
                    $paymentDetails = $this->paymentService->getSnapToken($order, $request->customer);
                    break;
                case 'duitku':
                    $paymentDetails = $this->paymentService->getDuitkuInvoice($order, $request->customer, $request->payment_method);
                    break;
                case 'tripay':
                    $paymentDetails = $this->paymentService->getTripayPayment($order, $request->payment_method, $request->customer);
                    break;
                default:
                    return response()->json([
                        'success' => false,
                        'message' => 'Payment Gateway tidak tersedia.'
                    ], 400);
            }

            // Tentukan parameter redirect url, token, dan reference
            $paymentUrl = $paymentDetails['redirect_url'] ?? null;
            $token = null;
            $reference = null;
            $expiredAt = date('Y-m-d H:i:s', strtotime('+24 hours'));

            if ($request->payment_gateway === 'midtrans') {
                $token = $paymentDetails['token'] ?? null;
            } else {
                $reference = $paymentDetails['token'] ?? null;
            }

            // Simpan detail Response Gateway ke Payments
            Payment::updateOrCreate(
                ['order_id' => $order->id],
                [
                    'payment_method' => $request->payment_method,
                    'status' => 'pending',
                    'payment_gateway' => $request->payment_gateway,
                    'payment_url' => $paymentUrl,
                    'token' => $token,
                    'reference' => $reference,
                    'expired_at' => $expiredAt,
                    'raw_response' => $paymentDetails
                ]
            );

            // 7. Mengembalikan URL pembayaran / Token
            $responsePayload = [
                'success' => true,
                'message' => 'Checkout berhasil',
                'invoice' => $order->invoice_number,
                'payment_gateway' => $request->payment_gateway,
                'gateway' => $request->payment_gateway,
                'payment_url' => $paymentUrl,
                'expired_at' => $expiredAt
            ];

            if ($request->payment_gateway === 'midtrans') {
                $responsePayload['token'] = $token;
            } else {
                $responsePayload['reference'] = $reference;
            }

            return response()->json($responsePayload);

        } catch (\Exception $e) {
            Log::error('Checkout API error: ' . $e->getMessage());
            return response()->json([
                'success' => false,
                'message' => 'Payment Gateway tidak tersedia.'
            ], 400);
        }
    }
}
