<?php

namespace App\Http\Controllers;

use App\Models\Pesanan;
use App\Models\User;
use App\Models\Pembayaran; 
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Midtrans\Config;
use Midtrans\Snap;
use Midtrans\Notification;

class PesananController extends Controller
{

    public function __construct()
    {
        Config::$serverKey = config('midtrans.server_key');
        Config::$isProduction = config('midtrans.is_production');
        Config::$isSanitized = true;
        Config::$is3ds = true;
    }

    /**
     * LIST PESANAN
     */
    public function index()
    {
        if (Auth::user()->role === 'admin') {

            $pesanans = Pesanan::with(['user','pembayaran'])
                ->where('status', '!=', 'menunggu')
                ->latest()
                ->get();

            return view('pesanans.index', compact('pesanans'));
        }

        $pesanans = Pesanan::with(['detailPesanans.produk','pembayaran'])
            ->where('user_id', Auth::id())
            ->latest()
            ->get();

        return view('customer.riwayat_pesanan', compact('pesanans'));
    }

    /**
     * FORM BUAT PESANAN
     */
    public function create()
    {
        $this->authorizeCustomer();

        return view('pesanans.create');
    }

    public function update(Request $request, Pesanan $pesanan)
    {
        // Validasi
        $request->validate([
            'status' => 'nullable|string|in:menunggu,diproses,dikirim,selesai,dibatalkan,bermasalah',
            'no_resi' => 'nullable|string|max:255',
            'kurir_id' => 'nullable|exists:users,id'
        ]);

        $noResi = $request->no_resi;
        $status = $request->status ?? $pesanan->status;

        // Cegah Admin update status ke 'dikirim' atau 'selesai' (Hanya kurir)
        if (Auth::user()->role === 'admin' && in_array($status, ['dikirim', 'selesai'])) {
            $status = $pesanan->status; // Tahan pada status sebelumnya
        }

        // Auto-generate resi jika status dikirim/diproses dan resi masih kosong
        if (in_array($status, ['diproses', 'dikirim']) && empty($noResi) && empty($pesanan->no_resi)) {
            $noResi = 'MFI-' . date('Ymd') . strtoupper(Str::random(4));
        }

        $updateData = [
            'status' => $status,
            'no_resi' => $noResi ?? $pesanan->no_resi
        ];

        // Jika kurir_id divalute explicit, maka update
        if ($request->has('kurir_id')) {
            $isNewKurir = $pesanan->kurir_id != $request->kurir_id;
            $updateData['kurir_id'] = $request->kurir_id;
            $newKurirId = $request->kurir_id;
        }

        $pesanan->update($updateData);

        // Notify courier if a new one is assigned
        if (isset($isNewKurir) && $isNewKurir && isset($newKurirId) && $newKurirId) {
            $kurir = User::find($newKurirId);
            if ($kurir) {
                $kurir->notify(new \App\Notifications\KurirDitugaskanNotification($pesanan));
            }
        }

        return redirect()->back()->with('success', 'Pesanan berhasil diupdate');
    }


    /**
     * SIMPAN PESANAN
     */
    public function store(Request $request)
    {
        $this->authorizeCustomer();

        $request->validate([
            'tanggal_pesanan' => 'required|date',
            'total_harga' => 'required|numeric'
        ]);

        $pesanan = Pesanan::create([
            'user_id' => Auth::id(),
            'tanggal_pesanan' => $request->tanggal_pesanan,
            'total_harga' => $request->total_harga,
            'status' => 'pending'
        ]);

        return redirect()->route('pesanans.show', $pesanan->id)
            ->with('success','Pesanan berhasil dibuat');
    }

    public function show(Pesanan $pesanan)
    {
        if (Auth::user()->role === 'customer' && $pesanan->user_id !== Auth::id()) {
            abort(403);
        }

        $pesanan->load('detailPesanans.produk','pembayaran','user', 'provinsi', 'regency', 'kecamatan', 'desa', 'kurir');

        if (Auth::user()->role === 'admin') {
            $kurirs = User::where('role', 'ekspedisi')->get();
            return view('pesanans.show', compact('pesanan', 'kurirs'));
        }

        return view('customer.detail_pesanan', compact('pesanan'));
    }

    public function detail($id)
    {
        $pesanan = Pesanan::findOrFail($id);
        return $this->show($pesanan);
    }

    /**
     * KONFIRMASI SELESAI OLEH CUSTOMER
     */
    public function konfirmasiSelesai(Pesanan $pesanan)
    {
        if (\Illuminate\Support\Facades\Auth::user()->role === 'customer' && $pesanan->user_id !== \Illuminate\Support\Facades\Auth::id()) {
            abort(403);
        }

        if ($pesanan->status !== 'dikirim') {
            return back()->with('error', 'Pesanan belum dalam status dikirim.');
        }

        $pesanan->update([
            'status' => 'selesai'
        ]);

        // Beri notifikasi ke pihak admin
        if(class_exists(\App\Models\User::class)) {
            $admins = \App\Models\User::where('role', 'admin')->get();
            if($admins->count() > 0) {
                // Gunakan kurir yang mengantar kalau ada
                $kurir = $pesanan->kurir ?? \Illuminate\Support\Facades\Auth::user();
                \Illuminate\Support\Facades\Notification::send($admins, new \App\Notifications\PesananSelesaiNotification($pesanan, $kurir));
            }
        }

        return back()->with('success', 'Pesanan telah dikonfirmasi selesai. Terima kasih!');
    }

    /**
     * BATALKAN CHECKOUT KEMBALI KE KERANJANG
     */
    public function batalkanCheckout(Pesanan $pesanan)
    {
        if (\Illuminate\Support\Facades\Auth::user()->role === 'customer' && $pesanan->user_id !== \Illuminate\Support\Facades\Auth::id()) {
            abort(403);
        }

        if ($pesanan->status !== 'menunggu') {
            return back()->with('error', 'Pesanan tidak dapat dibatalkan.');
        }

        \Illuminate\Support\Facades\DB::beginTransaction();
        try {
            // Restore stok & keranjang
            foreach ($pesanan->detailPesanans as $detail) {
                if ($detail->varian_id) {
                    $varian = \App\Models\ProdukVarian::find($detail->varian_id);
                } else {
                    // Fallback for buggy legacy orders where varian_id was null
                    $produk = \App\Models\Produk::with('varians')->find($detail->produk_id);
                    $varian = $produk ? $produk->varians->first() : null;
                }

                if ($varian) {
                    $stokLama = $varian->stok;
                    $varian->increment('stok', $detail->jumlah);
                    \App\Models\StockLog::create([
                        'produk_varian_id' => $varian->id,
                        'user_id' => \Illuminate\Support\Facades\Auth::id(),
                        'tipe_pergerakan' => 'in',
                        'jumlah' => $detail->jumlah,
                        'stok_sebelum' => $stokLama,
                        'stok_sesudah' => $stokLama + $detail->jumlah,
                        'keterangan' => 'Pembatalan Checkout (Kembali ke Keranjang)'
                    ]);
                }

                \App\Models\KeranjangItem::create([
                    'id_users' => \Illuminate\Support\Facades\Auth::id(),
                    'id_produk' => $detail->produk_id,
                    'produk_varian_id' => $varian ? $varian->id : null,
                    'jumlah' => $detail->jumlah
                ]);
            }

            $pesanan->detailPesanans()->delete();
            $pesanan->delete();

            \Illuminate\Support\Facades\DB::commit();
            return redirect()->route('cart.index')->with('success', 'Checkout dibatalkan, barang dikembalikan ke keranjang.');
        } catch (\Exception $e) {
            \Illuminate\Support\Facades\DB::rollBack();
            return back()->with('error', 'Gagal membatalkan checkout: ' . $e->getMessage() . ' di line ' . $e->getLine());
        }
    }

    /**
     * CETAK RESI
     */
    public function cetakResi(Pesanan $pesanan)
    {
        if (Auth::user()->role === 'customer' && $pesanan->user_id !== Auth::id()) {
            abort(403);
        }

        $pesanan->load('detailPesanans.produk', 'user', 'provinsi', 'regency', 'kecamatan', 'desa');

        return view('pesanans.cetak_resi', compact('pesanan'));
    }

    /**
     * CETAK LAPORAN PESANAN (PDF) - ADMIN
     */
    public function cetakLaporan()
    {
        if (Auth::user()->role !== 'admin') {
            abort(403);
        }

        $pesanans = Pesanan::with(['user', 'pembayaran'])
            ->latest()
            ->get();

        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('pesanans.pdf_laporan', compact('pesanans'))
            ->setPaper('a4', 'landscape');
            
        return $pdf->stream('laporan-pesanan-'.date('Y-m-d').'.pdf');
    }

    /**
     * CETAK INVOICE PESANAN (PDF) - ADMIN
     */
    public function cetakInvoiceAdmin(Pesanan $pesanan)
    {
        if (Auth::user()->role !== 'admin') {
            abort(403);
        }

        $pesanan->load('detailPesanans.produk', 'user', 'provinsi', 'regency', 'kecamatan', 'desa', 'pembayaran');

        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('pesanans.pdf_invoice', compact('pesanan'))
            ->setPaper('a4', 'portrait');

        return $pdf->stream('invoice-pesanan-'.$pesanan->id.'.pdf');
    }

    /**
     * MIDTRANS PAYMENT
     */
    public function bayar(Pesanan $pesanan)
    {
        if (\Illuminate\Support\Facades\Auth::user()->role === 'customer' && $pesanan->user_id !== \Illuminate\Support\Facades\Auth::id()) {
            abort(403);
        }
        $pesanan->load('detailPesanans.produk', 'provinsi', 'regency', 'kecamatan', 'desa');

        $orderId = 'ORDER-'.$pesanan->id.'-'.time();

        $params = [
            'transaction_details' => [
                'order_id' => $orderId,
                'gross_amount' => $pesanan->total_harga
            ],

            'customer_details' => [
                'name' => Auth::user()->nama,
                'email' => Auth::user()->email
            ]
        ];

        $snapToken = Snap::getSnapToken($params);

        return view('pesanans.process_checkout', compact('snapToken','pesanan'));
    }

    /**
     * CALLBACK MIDTRANS
     */
    public function callback()
{
    
    try {
        $notif = new Notification();
        
        // Ambil data dari notifikasi
        $transactionStatus = $notif->transaction_status;
        $paymentType = $notif->payment_type;
        $orderId = $notif->order_id;
        $fraudStatus = $notif->fraud_status;
        $transactionId = $notif->transaction_id ?? null;
        $grossAmount = $notif->gross_amount ?? null;
        
        // Log untuk debugging
        \Log::info('Midtrans Callback Received', [
            'order_id' => $orderId,
            'status' => $transactionStatus,
            'type' => $paymentType
        ]);
        
        // Ekstrak pesanan_id dari order_id (ORDER-{id}-{time})
        $orderParts = explode('-', $orderId);
        if (count($orderParts) < 2) {
            \Log::error('Invalid order_id format', ['order_id' => $orderId]);
            return response()->json(['error' => 'Invalid order_id'], 400);
        }
        
        $pesananId = $orderParts[1];
        $pesanan = Pesanan::find($pesananId);
        
        if (!$pesanan) {
            \Log::error('Pesanan not found', ['pesanan_id' => $pesananId]);
            return response()->json(['error' => 'Pesanan tidak ditemukan'], 404);
        }
        
        // Tentukan status pembayaran untuk database
        $transactionStatusDb = 'pending';
        if ($transactionStatus == 'capture') {
            $transactionStatusDb = ($fraudStatus == 'accept') ? 'berhasil' : 'gagal';
        } elseif ($transactionStatus == 'settlement') {
            $transactionStatusDb = 'berhasil';
        } elseif (in_array($transactionStatus, ['cancel', 'deny', 'expire'])) {
            $transactionStatusDb = 'gagal';
        } elseif ($transactionStatus == 'pending') {
            $transactionStatusDb = 'pending';
        }
        
        // CEK: Apakah tabel pembayarans sudah ada data untuk pesanan ini?
        $pembayaran = Pembayaran::where('pesanan_id', $pesanan->id)->first();
        
        if ($pembayaran) {
            // UPDATE data pembayaran yang sudah ada
            $pembayaran->update([
                'midtrans_order_id'  => $orderId,
                'payment_type'       => $paymentType,
                'transaction_status' => $transactionStatusDb,
                'transaction_id'     => $transactionId,
                'paid_at'            => ($transactionStatusDb == 'berhasil') ? now() : $pembayaran->paid_at,
            ]);
            
            \Log::info('Pembayaran updated', ['pembayaran_id' => $pembayaran->id]);
        } else {
            // CREATE data pembayaran baru
            $pembayaran = Pembayaran::create([
                'pesanan_id'         => $pesanan->id,
                'midtrans_order_id'  => $orderId,
                'payment_type'       => $paymentType,
                'transaction_status' => $transactionStatusDb,
                'transaction_id'     => $transactionId,
                'paid_at'            => ($transactionStatusDb == 'berhasil') ? now() : null,
            ]);
            
            \Log::info('Pembayaran created', ['pembayaran_id' => $pembayaran->id]);
        }
        
        // Update status pesanan (untuk jaga-jaga)
        if ($transactionStatusDb == 'berhasil') {
            $pesanan->update(['status' => 'diproses']);
        } elseif ($transactionStatusDb == 'gagal') {
            $pesanan->update(['status' => 'dibatalkan']);
        } elseif ($transactionStatusDb == 'pending') {
            // Status tetap pending
        }
        
        return response()->json([
            'status' => 'ok',
            'message' => 'Callback processed successfully',
            'data' => [
                'pesanan_id' => $pesanan->id,
                'payment_status' => $transactionStatusDb
            ]
        ]);
        
    } catch (\Exception $e) {
        \Log::error('Midtrans Callback Error', [
            'message' => $e->getMessage(),
            'trace' => $e->getTraceAsString()
        ]);
        
        return response()->json(['error' => $e->getMessage()], 500);
    }
}
}