<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Carbon\Carbon;
use App\Services\AccountingService;

class SalesInvoiceController extends Controller
{
    /**
     * TAB 1: FAKTUR SIAP CETAK (KEBERANGKATAN)
     */
    public function getReadyPrint(Request $request)
    {
        try {
            $user = $request->user();
            if (!$user) return response()->json(['success' => false, 'message' => 'Unauthenticated.'], 401);

            $requestedBranch = $request->query('branch_id');
            $branchId = ($user->role === 'owner') ? ($requestedBranch ?? 'all') : $user->branch_id;

            $query = DB::table('sales')
                ->leftJoin('customers', 'sales.customer_id', '=', 'customers.id') // FIX: leftJoin
                ->leftJoin('users as driver', 'sales.driver_id', '=', 'driver.id')
                ->select(
                    'sales.*', 
                    // FIX: Hapus customers.name dan customers.address, biarkan menggunakan bawaan sales.*
                    'driver.name as driver_name',
                    // (tetap biarkan DB::raw paid_amount jika ada di method tersebut)
                )
                ->whereIn('sales.delivery_status', ['pending', 'dikirim'])
                // PERBAIKAN: Sembunyikan faktur dummy (Saldo Awal Piutang) dari antrean logistik/gudang
                ->whereNotNull('sales.sales_order_id') 
                ->where('sales.delivery_status', '!=', 'void');

            if (!empty($branchId) && $branchId !== 'all' && $branchId !== 'null' && $branchId !== 'undefined') {
                $query->where('sales.branch_id', $branchId);
            }

            $data = $query->orderBy('sales.created_at', 'desc')->get();

            return response()->json(['success' => true, 'data' => $data]);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    /**
     * TAB 2: PIUTANG / VALIDASI SETORAN (KEDATANGAN)
     */
    public function getReceivables(Request $request)
    {
        try {
            $user = $request->user();
            if (!$user) return response()->json(['success' => false, 'message' => 'Unauthenticated.'], 401);

            $requestedBranch = $request->query('branch_id');
            $branchId = ($user->role === 'owner') ? ($requestedBranch ?? 'all') : $user->branch_id;

            $query = DB::table('sales')
                ->join('customers', 'sales.customer_id', '=', 'customers.id')
                ->leftJoin('users as driver', 'sales.driver_id', '=', 'driver.id')
                ->select(
                    'sales.*', 
                    'customers.name as customer_name', 
                    'customers.address as shipping_address',
                    'driver.name as driver_name',
                    DB::raw("(SELECT SUM(amount) FROM debt_payments WHERE sale_id = sales.id AND payment_status = 'completed') as paid_amount")
                )
                // PERBAIKAN: Di tab Piutang ini, Saldo Awal (tanpa SO) tetap dibiarkan MUNCUL agar bisa dilunasi.
                ->whereIn('sales.delivery_status', ['terkirim', 'selesai'])
                ->where('sales.payment_status', '!=', 'paid') 
                ->where('sales.delivery_status', '!=', 'void');

            if (!empty($branchId) && $branchId !== 'all' && $branchId !== 'null' && $branchId !== 'undefined') {
                $query->where('sales.branch_id', $branchId);
            }

            $data = $query->orderBy('sales.updated_at', 'desc')->get();

            return response()->json(['success' => true, 'data' => $data]);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    /**
     * TAB 3: HISTORI / BUKU BESAR
     */
    public function getHistory(Request $request)
    {
        try {
            $user = $request->user();
            if (!$user) return response()->json(['success' => false, 'message' => 'Unauthenticated.'], 401);

            $requestedBranch = $request->query('branch_id');
            $branchId = ($user->role === 'owner') ? ($requestedBranch ?? 'all') : $user->branch_id;

            $query = DB::table('sales')
                ->join('customers', 'sales.customer_id', '=', 'customers.id')
                ->leftJoin('users as driver', 'sales.driver_id', '=', 'driver.id')
                ->select(
                    'sales.*', 
                    'customers.name as customer_name', 
                    'customers.address as shipping_address',
                    'driver.name as driver_name',
                    DB::raw("(SELECT SUM(amount) FROM debt_payments WHERE sale_id = sales.id AND payment_status = 'completed') as paid_amount")
                )
                // PERBAIKAN: Sembunyikan faktur dummy (Saldo Awal Piutang) dari Histori Surat Jalan
                ->whereNotNull('sales.sales_order_id')
                ->where(function($q) {
                    $q->where('sales.payment_status', 'paid') 
                      ->orWhere('sales.delivery_status', 'void'); 
                });

            if (!empty($branchId) && $branchId !== 'all' && $branchId !== 'null' && $branchId !== 'undefined') {
                $query->where('sales.branch_id', $branchId);
            }

            $data = $query->orderBy('sales.updated_at', 'desc')->get();

            return response()->json(['success' => true, 'data' => $data]);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function getInvoiceDetail(Request $request, $id)
    {
        try {
            $user = $request->user();
            
            $query = DB::table('sales')
                ->leftJoin('customers', 'sales.customer_id', '=', 'customers.id')
                ->leftJoin('users as driver', 'sales.driver_id', '=', 'driver.id')
                ->leftJoin('sales_orders', 'sales.sales_order_id', '=', 'sales_orders.id')
                // TAMBAHAN: Join ke tabel branches untuk mendapatkan data cabang
                ->leftJoin('branches', 'sales.branch_id', '=', 'branches.id')
                ->select(
                    'sales.*', 
                    'customers.name as customer_name', 
                    'customers.address as shipping_address', 
                    'customers.is_pkp', 
                    'customers.default_tax_method', 
                    'driver.name as driver_name', 
                    'sales_orders.so_number',
                    // TAMBAHAN: Ambil kolom nama dan alamat dari tabel branches
                    'branches.name as branch_name',
                    'branches.address as branch_address',
                    DB::raw("(SELECT SUM(amount) FROM debt_payments WHERE sale_id = sales.id AND payment_status = 'completed') as paid_amount")
                )
                ->where('sales.id', $id);

            if ($user && $user->role !== 'owner') {
                $query->where('sales.branch_id', $user->branch_id);
            }

            $invoice = $query->first();

            if (!$invoice) return response()->json(['success' => false, 'message' => 'Faktur tidak ditemukan atau bukan milik cabang Anda.']);

            // TAMBAHAN: Bentuk ulang (format) data branch menjadi object agar sesuai dengan pembacaan frontend React (invoice.branch.name)
            if ($invoice->branch_id) {
                $invoice->branch = (object) [
                    'name' => $invoice->branch_name,
                    'address' => $invoice->branch_address
                ];
            } else {
                $invoice->branch = null;
            }

            $taxSetting = DB::table('settings')->where('key', 'ppn_rate')->first();
            $ppnRate = $taxSetting ? ((float) $taxSetting->value / 100) : 0.11;

            $subtotal = (float) $invoice->subtotal;
            $dpp = 0;
            $taxAmount = 0;
            $printGrandTotal = (float) $invoice->grand_total;

            if ($invoice->is_pkp == 0) {
                $dpp = $subtotal / (1 + $ppnRate);
                $taxAmount = $subtotal - $dpp;
            } else {
                if ($invoice->default_tax_method === 'exclude') {
                    $dpp = $subtotal;
                    $taxAmount = $dpp * $ppnRate;
                    $printGrandTotal = $subtotal + $taxAmount + (float)$invoice->shipping_fee;
                } elseif ($invoice->default_tax_method === 'include') {
                    $dpp = $subtotal / (1 + $ppnRate);
                    $taxAmount = $subtotal - $dpp;
                } else { 
                    $dpp = $subtotal;
                    $taxAmount = 0;
                }
            }

            $invoice->dpp = round($dpp, 2);
            $invoice->tax_amount = round($taxAmount, 2);
            $invoice->print_grand_total = round($printGrandTotal, 2);
            
            // =========================================================================
            // PERBAIKAN: Join ke tabel Products untuk mengambil variant_name
            // =========================================================================
            $items = DB::table('sale_items')
                ->leftJoin('products', 'sale_items.product_id', '=', 'products.id')
                ->select('sale_items.*', 'products.variant_name')
                ->where('sale_items.sale_id', $id)
                ->get();
                
            $soItems = DB::table('sales_order_items')->where('sales_order_id', $invoice->sales_order_id)->get();

            foreach ($items as $item) {
                $matchedSoItem = $soItems->first(function($soi) use ($item) {
                    return $soi->product_id == $item->product_id && $soi->unit_name == $item->unit;
                });

                if ($matchedSoItem) {
                    $item->real_unit_price = (float) $matchedSoItem->price; 
                    $discountPerUnit = ($matchedSoItem->qty > 0) ? ((float) $matchedSoItem->discount_nominal / $matchedSoItem->qty) : 0;
                    $item->total_discount = $discountPerUnit * (float) $item->quantity; 
                } else {
                    $item->real_unit_price = (float) $item->unit_price;
                    $item->total_discount = 0;
                }
            }

            $invoice->items = $items;

            return response()->json(['success' => true, 'data' => $invoice]);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function payInvoice(Request $request, $id)
    {
        $request->validate([
            'amount' => 'required|numeric|min:1',
            'payment_method' => 'required|string', 
            'account_id' => 'required|exists:accounts,id', 
            'note' => 'nullable|string'
        ]);

        $user = $request->user();

        DB::beginTransaction();
        try {
            $sale = DB::table('sales')->where('id', $id)->first();
            if (!$sale) throw new \Exception('Data Faktur tidak valid.');
            if ($sale->delivery_status === 'void') throw new \Exception('Tidak dapat memproses pembayaran untuk Faktur yang sudah di-VOID.');

            if ($user && $user->role !== 'owner' && $sale->branch_id !== $user->branch_id) {
                throw new \Exception('Akses ditolak: Faktur ini bukan wewenang cabang Anda.');
            }

            // PERBAIKAN: Validasi Rekening Bank Tujuan dengan Fallback yang aman
            if ($request->payment_method !== 'deposit' && $user && $user->role !== 'owner') {
                // Cek apakah mapping branch_accounts sudah diatur oleh Admin Pusat
                $hasMapping = DB::table('branch_accounts')->where('branch_id', $sale->branch_id)->exists();
                
                if ($hasMapping) {
                    $isMapped = DB::table('branch_accounts')
                        ->where('branch_id', $sale->branch_id)
                        ->where('account_id', $request->account_id)
                        ->where('is_active', 1)
                        ->exists();

                    if (!$isMapped) {
                        throw new \Exception('Akses ditolak (Security Lock): Akun penerimaan dana tidak terdaftar/aktif untuk cabang ini.');
                    }
                }
                // Jika $hasMapping false, sistem membiarkan transaksi lanjut agar operasional cabang tidak terhenti
            }

            $totalPaidSoFar = DB::table('debt_payments')->where('sale_id', $sale->id)->where('payment_status', 'completed')->sum('amount');
            $sisaTagihan = $sale->grand_total - $totalPaidSoFar;
            
            if ($request->amount > $sisaTagihan) throw new \Exception('Nominal bayar melebihi sisa tagihan.');

            $debitAccountId = $request->account_id;
            
            if ($request->payment_method === 'deposit') {
                $accUangMuka = AccountingService::getAccountId('deposit_pelanggan');
                if (!$accUangMuka) throw new \Exception("Sistem Gagal: Akun Uang Muka/Titipan Pelanggan belum dikonfigurasi di Master Akun.");
                $debitAccountId = $accUangMuka;
                
                $customer = DB::table('customers')->where('id', $sale->customer_id)->first();
                if (!$customer || $customer->deposit_balance < $request->amount) {
                    throw new \Exception('Saldo Titipan (DP) Pelanggan tidak mencukupi.');
                }
                
                DB::table('customers')->where('id', $sale->customer_id)
                    ->decrement('deposit_balance', $request->amount);
            }

            DB::table('debt_payments')->insert([
                'sale_id' => $sale->id,
                'branch_id' => $sale->branch_id,
                'amount' => $request->amount,
                'account_id' => $debitAccountId,
                'payment_method' => $request->payment_method,
                'payment_type' => 'receivable', 
                'payment_status' => 'completed',
                'payment_date' => Carbon::today()->toDateString(),
                'note' => $request->note,
                'user_id' => $user->id,
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now()
            ]);

            $accPiutang = AccountingService::getAccountId('receivable_account');
            if (!$accPiutang) throw new \Exception("Sistem Gagal: Akun Piutang Usaha belum di-mapping di Pengaturan Akuntansi.");
            
            AccountingService::log([
                'branch_id'   => $sale->branch_id,
                'entry_date'  => Carbon::today()->toDateString(),
                'description' => 'Penerimaan Pelunasan AR: ' . $sale->invoice_number . ' via ' . strtoupper($request->payment_method),
                'reference'   => 'PAY-AR-' . $sale->id,
                'source_type' => 'AR_PAYMENT',
                'user_id'     => $user->id,
                'items'       => [
                    ['account_id' => $debitAccountId, 'debit' => $request->amount, 'credit' => 0],
                    ['account_id' => $accPiutang, 'debit' => 0, 'credit' => $request->amount]
                ]
            ]);

            $newTotalPaid = $totalPaidSoFar + $request->amount;
            $paymentStatus = ($newTotalPaid >= $sale->grand_total) ? 'paid' : 'partial';
            
            DB::table('sales')->where('id', $sale->id)->update([
                'payment_status' => $paymentStatus,
                'payment_method' => $request->payment_method === 'deposit' ? 'kredit' : $request->payment_method, 
                'updated_at' => Carbon::now()
            ]);

            DB::commit();
            return response()->json(['success' => true, 'message' => 'Pembayaran/Pemotongan DP berhasil diproses dan dicatat di Jurnal!']);

        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => $e->getMessage()]);
        }
    }

    public function authorizeReprint(Request $request)
    {
        $request->validate(['password' => 'required']);

        try {
            $authorizedUsers = DB::table('users')
                ->whereIn('role', ['owner', 'manager', 'supervisor'])
                ->get();

            $isMatched = false;
            foreach ($authorizedUsers as $user) {
                if (Hash::check($request->password, $user->password)) {
                    $isMatched = true;
                    break;
                }
            }

            if (!$isMatched) {
                return response()->json(['success' => false, 'message' => 'Otorisasi Gagal! Password salah atau Anda tidak memiliki akses.']);
            }

            return response()->json(['success' => true]);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => 'Terjadi kesalahan sistem saat verifikasi.']);
        }
    }

    public function markPrinted(Request $request, $id)
    {
        $user = $request->user();

        try {
            $query = DB::table('sales')->where('id', $id);
            if ($user && $user->role !== 'owner') {
                $query->where('branch_id', $user->branch_id);
            }

            $updated = $query->update([
                'print_count' => DB::raw('print_count + 1'),
                'updated_at'  => Carbon::now()
            ]);

            if (!$updated) {
                return response()->json(['success' => false, 'message' => 'Nota tidak ditemukan atau bukan milik cabang Anda.']);
            }

            return response()->json(['success' => true]);
        } catch (\Exception $e) {
            return response()->json(['success' => false]);
        }
    }

    public function getCashBankAccounts(Request $request)
    {
        try {
            $user = $request->user();

            $query = DB::table('accounts')
                ->where('is_active', 1)
                ->where(function($q) {
                    $q->where('code', 'like', '1%') 
                      ->where(function($sq) {
                          $sq->where('name', 'like', '%Kas%')
                             ->orWhere('name', 'like', '%Bank%')
                             ->orWhere('name', 'like', '%Tunai%');
                      });
                })
                ->select('id', 'code', 'name')
                ->orderBy('code', 'asc');

            if ($user && $user->role !== 'owner') {
                $mappedIds = DB::table('branch_accounts')
                    ->where('branch_id', $user->branch_id)
                    ->where('is_active', 1)
                    ->pluck('account_id')
                    ->toArray();

                // PERBAIKAN: Jika mapping belum ada (kosong), biarkan sistem menarik semua akun Kas 
                // agar UI tidak rusak dan Kasir tetap bisa bekerja.
                if (!empty($mappedIds)) {
                    $query->whereIn('id', $mappedIds);
                }
            }

            $accounts = $query->get();

            return response()->json([
                'success' => true,
                'data' => $accounts
            ]);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    
}