<?php

namespace App\Http\Controllers;

use App\Models\Order;
use App\Models\OrderItem;
use App\Models\Payment;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class PaymentController extends Controller
{
    private function blockAdmin()
    {
        if (!Auth::check() || Auth::user()->role === 'admin') {
            abort(403, 'Admin tidak boleh melakukan pembayaran');
        }
    }

    public function create(Order $order)
    {
        $this->blockAdmin();

        if (Auth::id() != $order->user_id) {
            abort(403, 'Unauthorized');
        }

        if (!$order->isProcess()) {
            return redirect()->route('order.show', $order->order_id)
                ->with('error', 'Order sudah diproses atau dibatalkan.');
        }

        // Jika sudah ada payment yang pending, langsung ke halaman payment
        $existingPayment = $order->payment;
        if ($existingPayment && $existingPayment->isUnpaid()) {
            return redirect()->route('payment.show', $existingPayment->id);
        }

        return view('payment.create', compact('order'));
    }

    public function store(Request $request, Order $order)
    {
        $this->blockAdmin();

        $user = Auth::user();

        // VALIDASI ALAMAT
        if (!$user->addresses()->exists()) {
            return redirect()
                ->route('payment.create', $order->order_id)
                ->with('error', 'Silakan tambahkan alamat pengiriman terlebih dahulu.');
        }

        $validated = $request->validate([
            'payment_method'  => 'required|in:cash,card,transfer,ewallet,qris',
            'payment_channel' => 'nullable|string',
        ]);

        if (Auth::id() != $order->user_id) {
            abort(403, 'Unauthorized');
        }

        if ($order->status !== 'pending') {
            return redirect()->route('order.show', $order->order_id)
                ->with('error', 'Order tidak valid.');
        }

        DB::beginTransaction();
        try {
            // HANDLE REMOVED ITEMS
            if ($request->has('removed_items')) {
                $removedItems = json_decode($request->removed_items, true);
                if (!empty($removedItems)) {
                    OrderItem::whereIn('id', $removedItems)
                        ->where('order_id', $order->order_id)
                        ->delete();

                    Log::info('Removed items from order', [
                        'order_id'      => $order->order_id,
                        'removed_items' => $removedItems,
                    ]);
                }
            }

            // HANDLE QUANTITY UPDATES
            if ($request->has('updated_quantities')) {
                $quantities = json_decode($request->updated_quantities, true);

                foreach ($quantities as $itemId => $newQuantity) {
                    $orderItem = OrderItem::where('id', $itemId)
                        ->where('order_id', $order->order_id)
                        ->first();

                    if ($orderItem) {
                        $product = $orderItem->product;
                        if ($product && $product->stock && $newQuantity > $product->stock) {
                            throw new \Exception("Stok produk {$product->product_name} tidak mencukupi. Tersedia: {$product->stock}");
                        }

                        $oldSubtotal         = $orderItem->subtotal;
                        $orderItem->quantity = $newQuantity;
                        $orderItem->subtotal = $orderItem->price * $newQuantity;
                        $orderItem->save();

                        Log::info('Updated item quantity', [
                            'item_id'      => $itemId,
                            'old_qty'      => $orderItem->getOriginal('quantity'),
                            'new_qty'      => $newQuantity,
                            'old_subtotal' => $oldSubtotal,
                            'new_subtotal' => $orderItem->subtotal,
                        ]);
                    }
                }
            }

            // Pastikan order masih punya item
            $remainingItems = $order->items()->count();
            if ($remainingItems === 0) {
                throw new \Exception('Tidak dapat memproses pesanan kosong.');
            }

            // RECALCULATE ORDER TOTAL (produk subtotal + ongkos kirim)
            $itemsSubtotal      = $order->items()->sum('subtotal');
            $newTotal           = $itemsSubtotal + (int) $order->shipping_cost;
            $order->total_price = $newTotal;
            $order->save();

            Log::info('Order totals recalculated', [
                'order_id'      => $order->order_id,
                'old_total'     => $order->getOriginal('total_price'),
                'items_subtotal'=> $itemsSubtotal,
                'shipping_cost' => $order->shipping_cost,
                'new_total'     => $newTotal,
                'item_count'    => $remainingItems,
            ]);

            $paymentMethod  = $validated['payment_method'];
            $paymentChannel = $validated['payment_channel'] ?? null;

            // ── COD / Cash ────────────────────────────────────────────────────
            // Invoice TIDAK dikirim sekarang. Akan dikirim saat admin konfirmasi paid.
            if ($paymentMethod === 'cash') {
                Payment::create([
                    'order_id'        => $order->order_id,
                    'payment_method'  => $paymentMethod,
                    'payment_channel' => $paymentChannel,
                    'amount'          => $order->total_price,
                    'status'          => 'unpaid',
                ]);

                $order->update(['status' => 'process']);

                DB::commit();
                Log::info('COD payment created (unpaid) — invoice pending admin confirmation', [
                    'order_id' => $order->order_id,
                ]);

                return redirect()->route('order.show', $order->order_id)
                    ->with('success', 'Order berhasil dibuat! Pembayaran akan dilakukan saat barang tiba.');
            }

            // ── Online Payment (Midtrans) ──────────────────────────────────────
            $payment = Payment::create([
                'order_id'        => $order->order_id,
                'payment_method'  => $paymentMethod,
                'payment_channel' => $paymentChannel,
                'amount'          => $order->total_price,
                'status'          => 'unpaid',
            ]);

            $snapData = $this->createMidtransSnap($order, $payment);

            $payment->update([
                'midtrans_order_id'    => $snapData['order_id'],
                'midtrans_snap_token'  => $snapData['snap_token'],
                'midtrans_payment_url' => $snapData['payment_url'],
                'expired_at'           => now()->addDay(),
            ]);

            $order->update(['status' => 'process']);

            DB::commit();
            Log::info('Payment created with Midtrans', [
                'payment_id'        => $payment->id,
                'midtrans_order_id' => $snapData['order_id'],
                'total_amount'      => $order->total_price,
            ]);

            return redirect()->route('payment.show', $payment->id);

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Payment creation failed: ' . $e->getMessage(), [
                'order_id' => $order->order_id,
                'trace'    => $e->getTraceAsString(),
            ]);

            return redirect()->back()
                ->with('error', 'Gagal membuat pembayaran: ' . $e->getMessage())
                ->withInput();
        }
    }

    public function show(Payment $payment)
    {
        $this->blockAdmin();

        if (Auth::id() != $payment->order->user_id) {
            abort(403, 'Unauthorized');
        }

        $payment->load('order.items.product');
        return view('payment.show', compact('payment'));
    }

    public function checkStatus(Payment $payment)
    {
        $this->blockAdmin();

        if (Auth::id() != $payment->order->user_id) {
            abort(403, 'Unauthorized');
        }

        try {
            // Sudah paid — langsung return, tidak perlu cek Midtrans lagi
            if ($payment->isPaid()) {
                return response()->json([
                    'success' => true,
                    'status'  => 'paid',
                    'message' => 'Pembayaran sudah selesai.',
                ]);
            }

            // Sudah failed / expired
            if (in_array($payment->status, ['failed', 'expired'])) {
                return response()->json([
                    'success' => false,
                    'status'  => $payment->status,
                    'message' => 'Pembayaran ' . $payment->status . '.',
                ]);
            }

            // Tidak ada midtrans_order_id → tidak bisa cek ke Midtrans
            if (!$payment->midtrans_order_id) {
                return response()->json([
                    'success' => false,
                    'status'  => 'unknown',
                    'message' => 'Tidak ada data transaksi Midtrans.',
                ], 400);
            }

            // ── Cek ke Midtrans ───────────────────────────────────────────────
            \Midtrans\Config::$serverKey    = config('services.midtrans.server_key');
            \Midtrans\Config::$isProduction = config('services.midtrans.is_production');
            \Midtrans\Config::$isSanitized  = true;
            \Midtrans\Config::$is3ds        = true;

            $status            = \Midtrans\Transaction::status($payment->midtrans_order_id);
            $transactionStatus = strtolower($status->transaction_status ?? '');
            $fraudStatus       = strtolower($status->fraud_status ?? 'accept');

            Log::info('checkStatus Midtrans', [
                'payment_id'         => $payment->id,
                'midtrans_order_id'  => $payment->midtrans_order_id,
                'transaction_status' => $transactionStatus,
                'fraud_status'       => $fraudStatus,
            ]);

            // ── PAID / SETTLEMENT ─────────────────────────────────────────────
            if (
                ($transactionStatus === 'capture' && $fraudStatus === 'accept') ||
                $transactionStatus === 'settlement'
            ) {
                DB::beginTransaction();
                try {
                    $payment->update([
                        'status'                  => 'paid',
                        'payment_date'            => now(),
                        'midtrans_transaction_id' => $status->transaction_id ?? null,
                    ]);

                    DB::commit();

                    // ── Kirim invoice otomatis setelah payment online confirmed ──
                    // Invoice dikirim di luar transaction agar error email tidak
                    // membatalkan update status payment.
                    /** @var \App\Http\Controllers\InvoiceController $invoiceCtrl */
                    $invoiceCtrl = app(InvoiceController::class);
                    $invoiceCtrl->sendInvoiceAfterPayment($payment->fresh()->order);

                    return response()->json([
                        'success' => true,
                        'status'  => 'paid',
                        'message' => 'Pembayaran berhasil dikonfirmasi!',
                    ]);
                } catch (\Exception $e) {
                    DB::rollBack();
                    Log::error('Gagal update payment paid: ' . $e->getMessage());

                    return response()->json([
                        'success' => false,
                        'status'  => 'error',
                        'message' => 'Gagal memproses konfirmasi: ' . $e->getMessage(),
                    ], 500);
                }
            }

            // ── PENDING ───────────────────────────────────────────────────────
            if ($transactionStatus === 'pending') {
                return response()->json([
                    'success' => true,
                    'status'  => 'pending',
                    'message' => 'Pembayaran masih menunggu.',
                ]);
            }

            // ── FAILED / EXPIRED / CANCEL / DENY ─────────────────────────────
            if (in_array($transactionStatus, ['deny', 'expire', 'cancel', 'failure'])) {
                DB::beginTransaction();
                try {
                    $payment->update(['status' => 'failed']);
                    DB::commit();
                } catch (\Exception $e) {
                    DB::rollBack();
                    Log::error('Gagal update payment failed: ' . $e->getMessage());
                }

                return response()->json([
                    'success' => false,
                    'status'  => 'failed',
                    'message' => 'Pembayaran ' . $transactionStatus . '.',
                ]);
            }

            // Status lain yang tidak dikenali
            return response()->json([
                'success' => true,
                'status'  => $transactionStatus,
                'message' => 'Status pembayaran: ' . $transactionStatus,
            ]);

        } catch (\Midtrans\Exceptions\MidtransApiException $e) {
            Log::warning('Midtrans API Exception: ' . $e->getMessage(), [
                'payment_id'        => $payment->id,
                'midtrans_order_id' => $payment->midtrans_order_id,
            ]);

            if ($e->getCode() === 404 || str_contains($e->getMessage(), '404')) {
                return response()->json([
                    'success' => false,
                    'status'  => 'not_found',
                    'message' => 'Transaksi tidak ditemukan di Midtrans.',
                ], 404);
            }

            return response()->json([
                'success' => false,
                'status'  => 'error',
                'message' => 'Gagal cek status Midtrans: ' . $e->getMessage(),
            ], 500);

        } catch (\Exception $e) {
            Log::error('checkStatus error: ' . $e->getMessage(), [
                'payment_id' => $payment->id,
            ]);

            return response()->json([
                'success' => false,
                'status'  => 'error',
                'message' => 'Gagal cek status: ' . $e->getMessage(),
            ], 500);
        }
    }

    /**
     * Konfirmasi pembayaran COD oleh admin.
     * PATCH /admin/payments/{payment}/confirm-cash
     *
     * Setelah payment COD dikonfirmasi paid → invoice dikirim ke customer.
     */
    public function adminConfirmCash(Payment $payment)
    {
        // Hanya admin
        if (!Auth::check() || Auth::user()->role !== 'admin') {
            abort(403, 'Unauthorized');
        }

        if ($payment->payment_method !== 'cash') {
            return back()->with('error', 'Konfirmasi ini hanya untuk pembayaran COD.');
        }

        if ($payment->isPaid()) {
            return back()->with('error', 'Pembayaran sudah dikonfirmasi sebelumnya.');
        }

        DB::beginTransaction();
        try {
            $payment->update([
                'status'       => 'paid',
                'payment_date' => now(),
            ]);

            DB::commit();

            // ── Kirim invoice setelah COD dikonfirmasi ──
            /** @var \App\Http\Controllers\InvoiceController $invoiceCtrl */
            $invoiceCtrl = app(InvoiceController::class);
            $invoiceCtrl->sendInvoiceAfterPayment($payment->fresh()->order);

            Log::info('COD payment confirmed by admin — invoice sent', [
                'payment_id' => $payment->id,
                'order_id'   => $payment->order_id,
                'admin_id'   => Auth::id(),
            ]);

            return back()->with('success', 'Pembayaran COD dikonfirmasi dan invoice dikirim ke customer.');

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Gagal konfirmasi COD: ' . $e->getMessage(), [
                'payment_id' => $payment->id,
            ]);

            return back()->with('error', 'Gagal konfirmasi pembayaran: ' . $e->getMessage());
        }
    }

    // ── PRIVATE HELPERS ───────────────────────────────────────────────────────

    private function createMidtransSnap(Order $order, Payment $payment): array
    {
        try {
            \Midtrans\Config::$serverKey    = config('services.midtrans.server_key');
            \Midtrans\Config::$isProduction = config('services.midtrans.is_production');
            \Midtrans\Config::$isSanitized  = true;
            \Midtrans\Config::$is3ds        = true;

            $orderId         = strtoupper($payment->payment_method) . '-' . $order->order_id . '-' . time();
            $enabledPayments = $this->getEnabledPayments($payment->payment_method);

            $itemDetails = [];
            foreach ($order->items as $item) {
                $itemDetails[] = [
                    'id'       => $item->product_id,
                    'price'    => (int) ($item->subtotal / $item->quantity),
                    'quantity' => $item->quantity,
                    'name'     => substr($item->product->product_name, 0, 50),
                ];
            }

            // Tambahkan ongkos kirim sebagai item agar sum item_details = gross_amount
            if ($order->shipping_cost > 0) {
                $itemDetails[] = [
                    'id'       => 'SHIPPING',
                    'price'    => (int) $order->shipping_cost,
                    'quantity' => 1,
                    'name'     => 'Ongkos Kirim (' . ($order->courier_name ?? $order->courier_code ?? 'Kurir') . ')',
                ];
            }

            $params = [
                'transaction_details' => [
                    'order_id'     => $orderId,
                    'gross_amount' => (int) $order->total_price,
                ],
                'item_details'     => $itemDetails,
                'enabled_payments' => $enabledPayments,
                'customer_details' => [
                    'first_name' => $order->user->name,
                    'email'      => $order->user->email,
                ],
                'expiry' => [
                    'duration' => $payment->payment_method === 'qris' ? 15 : 24,
                    'unit'     => $payment->payment_method === 'qris' ? 'minutes' : 'hours',
                ],
            ];

            $snapToken  = \Midtrans\Snap::getSnapToken($params);
            $paymentUrl = config('services.midtrans.is_production')
                ? 'https://app.midtrans.com/snap/v2/vtweb/' . $snapToken
                : 'https://app.sandbox.midtrans.com/snap/v2/vtweb/' . $snapToken;

            return [
                'order_id'    => $orderId,
                'snap_token'  => $snapToken,
                'payment_url' => $paymentUrl,
            ];
        } catch (\Exception $e) {
            Log::error('Midtrans Snap failed: ' . $e->getMessage());
            throw new \Exception('Gagal membuat pembayaran: ' . $e->getMessage());
        }
    }

    private function getEnabledPayments(string $paymentMethod): array
    {
        $isProduction = config('services.midtrans.is_production');

        return [
            'card'     => ['credit_card'],
            'qris'     => $isProduction ? ['qris'] : ['gopay'],
            'transfer' => ['bca_va', 'bni_va', 'bri_va', 'echannel', 'permata_va', 'other_va'],
            'ewallet'  => $isProduction
                ? ['gopay', 'shopeepay', 'qris', 'dana', 'linkaja', 'ovo']
                : ['gopay', 'shopeepay', 'dana', 'linkaja', 'ovo'],
        ][$paymentMethod] ?? [];
    }
}