<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Models\CanvasStock;
use App\Models\CanvasLoading;
use App\Models\CanvasLoadingItem;
use App\Models\SalesOrder; 
use Carbon\Carbon;
use App\Services\AccountingService;

class CanvasSalesController extends Controller
{
    /**
     * ========================================================================
     * FITUR BARU: AUTO-GRADING PELANGGAN BERDASARKAN UMUR PIUTANG (AR AGING)
     * ========================================================================
     */
    private function _calculateCustomerGrade($customerId)
    {
        // Tarik data 3 bulan terakhir (90 Hari)
        $threeMonthsAgo = Carbon::today()->subDays(90)->toDateString();

        $creditSales = DB::table('sales')
            ->where('customer_id', $customerId)
            ->where('payment_method', 'kredit')
            ->where('delivery_status', '!=', 'void')
            ->where('created_at', '>=', $threeMonthsAgo)
            ->get();

        if ($creditSales->isEmpty()) {
            return 'A'; 
        }

        $maxDaysToPay = 0;

        foreach ($creditSales as $sale) {
            $invoiceDate = Carbon::parse($sale->created_at);

            $lastPayment = DB::table('debt_payments')
                ->where('sale_id', $sale->id)
                ->where('payment_status', 'completed')
                ->orderBy('payment_date', 'desc')
                ->first();

            if ($sale->payment_status === 'paid' && $lastPayment) {
                $payDate = Carbon::parse($lastPayment->payment_date);
                $days = $invoiceDate->diffInDays($payDate);
            } else {
                $days = $invoiceDate->diffInDays(Carbon::today());
            }

            if ($days > $maxDaysToPay) {
                $maxDaysToPay = $days;
            }
        }

        if ($maxDaysToPay <= 30) return 'A'; 
        if ($maxDaysToPay <= 60) return 'B'; 
        if ($maxDaysToPay <= 90) return 'C'; 
        return 'D';                                  
    }

    /**
     * ========================================================================
     * ENDPOINT BARU: KATALOG PRODUK KHUSUS KANVAS (HANYA STOK DI MOBIL)
     * ========================================================================
     */
    public function getCanvasProducts(Request $request)
    {
        $request->validate([
            'customer_id' => 'required|exists:customers,id'
        ]);

        $user = $request->user();
        $branchId = $user->branch_id;

        $customer = DB::table('customers')
            ->where('id', $request->customer_id)
            ->where('branch_id', $branchId)
            ->first();

        if (!$customer) {
            return response()->json(['success' => false, 'message' => 'Akses ditolak.'], 403);
        }

        preg_match('/\d+/', $customer->price_level ?? '1', $matches);
        $customerLevel = isset($matches[0]) ? (int)$matches[0] : 1;

        $salesman = DB::table('salesmen')->where('user_id', $user->id)->first();
        if (!$salesman) {
            return response()->json(['success' => false, 'message' => 'Data salesman tidak valid.'], 403);
        }

        // Ambil produk yang ADA DI MOBIL (Tabel canvas_stocks)
        $canvasStocks = \App\Models\CanvasStock::where('salesman_id', $salesman->id)
            ->where('quantity', '>', 0)
            ->get()
            ->keyBy('product_id');

        $productIds = $canvasStocks->keys();

        if ($productIds->isEmpty()) {
            return response()->json([
                'success' => true,
                'customer_info' => [
                    'id' => $customer->id,
                    'name' => $customer->name,
                    'level' => $customerLevel,
                    'credit_limit' => (float) $customer->credit_limit
                ],
                'data' => []
            ], 200);
        }

        $products = \App\Models\Product::with(['category', 'prices'])
            ->whereIn('id', $productIds)
            ->where('is_active', 1)
           ->whereIn('product_type', ['trading', 'finished_good'])
            ->get();

        $formattedProducts = [];

        foreach ($products as $product) {
            $availableStock = (float) ($canvasStocks[$product->id]->quantity ?? 0);

            $validPrices = [];
            if ($product->prices && count($product->prices) > 0) {
                foreach ($product->prices as $p) {
                    preg_match('/\d+/', $p->level ?? '1', $pMatches);
                    $priceLevelNum = isset($pMatches[0]) ? (int)$pMatches[0] : 1;

                    if ($priceLevelNum === $customerLevel) {
                        $resolvedUnitName = $p->unit_name;
                        if (empty($resolvedUnitName)) {
                            $uLevel = (int) ($p->unit_level ?? 1);
                            if ($uLevel === 2) $resolvedUnitName = $product->buy_unit ?? $product->satuan_besar ?? 'DUS';
                            elseif ($uLevel === 3) $resolvedUnitName = $product->unit_3_name ?? $product->satuan_l3 ?? 'BAL';
                            elseif ($uLevel === 4) $resolvedUnitName = $product->unit_4_name ?? $product->satuan_l4 ?? 'TRUK';
                            else $resolvedUnitName = $product->satuan_dasar ?? $product->unit ?? 'PCS';
                        }

                        $validPrices[] = [
                            'id' => $product->id,
                            'unit_level' => $p->unit_level ?? '1', // WAJIB ADA UNTUK FLUTTER
                            'unit_name' => strtoupper(trim($resolvedUnitName)),
                            'min_qty' => (int) ($p->min_qty ?? 1),
                            'price' => (float) $p->amount
                        ];
                    }
                }
            }

            if (empty($validPrices)) {
                $validPrices[] = [
                    'id' => $product->id,
                    'unit_level' => '1',
                    'unit_name' => strtoupper(trim($product->satuan_dasar ?? $product->unit ?? 'PCS')),
                    'min_qty' => 1,
                    'price' => (float) ($product->price ?? 0)
                ];
            }

            $formattedProducts[] = [
                'id' => $product->id,
                'name' => $product->variant_name ? $product->name . ' - ' . $product->variant_name : $product->name,
                'category' => $product->category ? $product->category->name : 'Umum',
                'available_stock' => $availableStock,
                'base_unit' => $product->satuan_dasar ?? $product->unit ?? 'PCS',
                'price_reference_level' => (int) ($product->price_reference_level ?? 1), // <--- PENAMBAHAN ACUAN JUAL
                'prices' => $validPrices,
            ];
        }

        return response()->json([
            'success' => true,
            'customer_info' => [
                'id' => $customer->id,
                'name' => $customer->name,
                'level' => $customerLevel,
                'credit_limit' => (float) $customer->credit_limit
            ],
            'data' => $formattedProducts
        ], 200);
    }

    /**
     * ENDPOINT: AMBIL MASTER DATA KHUSUS KANVAS
     */
    public function getMasterData(Request $request)
    {
        try {
            $user = $request->user();

            $customerQuery = DB::table('customers')
                ->where('is_active', 1)
                ->select('id', 'name', 'customer_code', 'address', 'price_level', 'credit_limit', 'salesman_id', 'due_days', 'is_pkp', 'default_tax_method')
                ->orderBy('name', 'asc');

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

            $customers = $customerQuery->get();

            $parentIds = DB::table('products')
                ->whereNotNull('variant_group_id')
                ->pluck('variant_group_id')
                ->map(function($val) {
                    return (int) str_replace('VAR-', '', $val);
                })
                ->filter()
                ->unique()
                ->toArray();

            $products = DB::table('products')
                ->where('is_active', 1)
                ->whereIn('product_type', ['trading', 'finished_good'])
                ->orderBy('name', 'asc')
                ->get();

            $productPrices = DB::table('product_prices')->get();
            $pricesGrouped = collect($productPrices)->groupBy('product_id');

            foreach ($products as $product) {
                $product->name = $product->variant_name ? $product->name . ' - ' . $product->variant_name : $product->name;
                $product->prices = $pricesGrouped->get($product->id, []);
            }

            $salesmenQuery = DB::table('salesmen')
                ->join('users', 'salesmen.user_id', '=', 'users.id')
                ->where('salesmen.salesman_type', 'CANVAS')
                ->select('salesmen.id', 'users.name', 'salesmen.salesman_type');

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

            $salesmen = $salesmenQuery->get();

            // TAMBAHAN: Tarik stok kanvas untuk memfilter produk di frontend
            $canvasStocksQuery = DB::table('canvas_stocks')->where('quantity', '>', 0);
            if ($user && $user->role !== 'owner') {
                $canvasStocksQuery->where('branch_id', $user->branch_id);
            }
            $canvasStocks = $canvasStocksQuery->select('salesman_id', 'product_id', 'quantity')->get();

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

    /**
     * FUNGSI PRIVATE: KALKULASI AMAN DI SISI SERVER (ANTI-TAMPERING)
     */
    private function _calculateCanvasCart($customerId, $items, $taxMethod)
    {
        try {
            $customer = DB::table('customers')->where('id', $customerId)->first();
            
            $subtotal = 0;
            $globalDiscount = 0;
            $processedItems = [];
            $bonusItems = [];

            $today = Carbon::today()->toDateString();
            $activePrograms = DB::table('sales_programs')
                ->where('is_active', 1)
                ->where('start_date', '<=', $today)
                ->where('end_date', '>=', $today)
                ->get();

            foreach ($items as $reqItem) {
                $qty = (float) ($reqItem['qty'] ?? 0);
                if ($qty <= 0) continue;

                $product = DB::table('products')->where('id', $reqItem['product_id'])->first();
                if (!$product) continue;

                $basePrice = (float) ($reqItem['price'] ?? 0);
                $itemTotalPrice = $basePrice * $qty;
                $itemDiscount = 0;
                $appliedProgramId = null;

                foreach ($activePrograms as $promo) {
                    $targetTypes = is_string($promo->target_customer_types) ? json_decode($promo->target_customer_types, true) : $promo->target_customer_types;
                    
                    if (!empty($targetTypes) && is_array($targetTypes) && count($targetTypes) > 0) {
                        if (!in_array($customer->customer_type_id, $targetTypes)) {
                            continue; 
                        }
                    }

                    $isMatch = false;
                    
                    if ($promo->scope === 'global') $isMatch = true;
                    elseif ($promo->scope === 'category' && $promo->category_id == $product->category_id) $isMatch = true;
                    elseif ($promo->scope === 'product' && $promo->product_id == $product->id) $isMatch = true;

                    if ($isMatch) {
                        $validTier = DB::table('sales_program_tiers')
                            ->where('sales_program_id', $promo->id)
                            ->where('min_qty', '<=', $qty)
                            ->orderBy('min_qty', 'desc')
                            ->first();

                        if ($validTier) {
                            $appliedProgramId = $promo->id;
                            $multiplier = ($validTier->is_multiple) ? floor($qty / $validTier->min_qty) : 1;
                            
                            if ($validTier->reward_type === 'discount_percent') {
                                $pct = (float) $validTier->reward_value;
                                $itemDiscount = $itemTotalPrice * ($pct / 100);
                            } elseif ($validTier->reward_type === 'discount_nominal') {
                                $itemDiscount = (float) $validTier->reward_value * $multiplier;
                            } elseif ($validTier->reward_type === 'bonus_item') {
                                $bonusProduct = DB::table('products')->where('id', $validTier->bonus_product_id)->first();
                                if ($bonusProduct) {
                                    $bonusFullName = $bonusProduct->variant_name 
                                        ? $bonusProduct->name . ' - ' . $bonusProduct->variant_name 
                                        : $bonusProduct->name;

                                    $bonusItems[] = [
                                        'product_id' => $bonusProduct->id,
                                        'product_name' => $bonusFullName,
                                        'qty' => $validTier->bonus_qty * $multiplier,
                                        'unit' => $bonusProduct->unit ?? 'Pcs',
                                        'program_name' => $promo->nama_program
                                    ];
                                }
                            }
                            break; 
                        }
                    }
                }

                $netTotalPrice = $itemTotalPrice - $itemDiscount;
                $subtotal += $itemTotalPrice;
                $globalDiscount += $itemDiscount;

                $productFullName = $product->variant_name 
                    ? $product->name . ' - ' . $product->variant_name 
                    : $product->name;

                $processedItems[] = [
                    'product_id' => $product->id,
                    'product_name' => $productFullName,
                    'qty' => $qty,
                    'unit' => $reqItem['unit_name'] ?? $reqItem['unit'] ?? 'Pcs',
                    'price' => $basePrice,
                    'discount_amount' => $itemDiscount,
                    'total_price' => $netTotalPrice,
                    'applied_program_id' => $appliedProgramId
                ];
            }

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

            $netTotalCart = $subtotal - $globalDiscount;

            $dpp = 0;
            $taxAmount = 0;
            $grandTotal = 0;

            if ($taxMethod === 'exclude') {
                $dpp = $netTotalCart;
                $taxAmount = $dpp * $ppnRate;
                $grandTotal = $dpp + $taxAmount;
            } elseif ($taxMethod === 'include') {
                $grandTotal = $netTotalCart;
                $dpp = $grandTotal / (1 + $ppnRate);
                $taxAmount = $grandTotal - $dpp;
            } else {
                $dpp = $netTotalCart;
                $taxAmount = 0;
                $grandTotal = $dpp;
            }

            return [
                'success' => true,
                'data' => [
                    'subtotal' => $subtotal,
                    'discount_amount' => $globalDiscount,
                    'dpp' => round($dpp, 2),
                    'tax_amount' => round($taxAmount, 2),
                    'grand_total' => round($grandTotal, 2),
                    'tax_method' => $taxMethod,
                    'items' => $processedItems,
                    'bonus_items' => $bonusItems
                ]
            ];

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

    public function calculateCart(Request $request)
    {
        $request->validate([
            'customer_id' => 'required',
            'items' => 'required|array',
            'tax_method' => 'nullable|in:non,include,exclude'
        ]);

        $result = $this->_calculateCanvasCart(
            $request->customer_id, 
            $request->items, 
            $request->tax_method ?? 'include'
        );
        
        return response()->json($result);
    }

    /**
     * ========================================================================
     * SIMPAN PESANAN KANVAS DENGAN CREDIT HOLD & LOCK FOR UPDATE
     * ========================================================================
     */
    public function storeManualOrder(Request $request)
    {
        $request->validate([
            'customer_id' => 'required',
            'salesman_id' => 'required',
            'payment_type' => 'required|in:tunai,kredit',
            'items' => 'required|array',
        ]);

        $userId = auth()->id();
        $user = auth()->user();
        if (!$userId) return response()->json(['success' => false, 'message' => 'Sesi tidak valid.'], 401);

        $branchId = $user->branch_id ?? 1;

        $salesman = DB::table('salesmen')->where('id', $request->salesman_id)->first();
        if (!$salesman) return response()->json(['success' => false, 'message' => 'Salesman tidak valid.'], 400);

        DB::beginTransaction();
        try {
            $backendPaymentMethod = $request->payment_type === 'tunai' ? 'cash' : 'kredit';

            $secureCalc = $this->_calculateCanvasCart($request->customer_id, $request->items, 'include');

            if (!$secureCalc['success']) {
                throw new \Exception("Gagal menghitung validasi keranjang: " . $secureCalc['message']);
            }
            $calc = $secureCalc['data']; 

            // 1. KUNCI PELANGGAN (Cegah Race Condition / Double Submit)
            $customer = DB::table('customers')->where('id', $request->customer_id)->lockForUpdate()->first();
            
            if (!$customer || (isset($customer->is_active) && $customer->is_active == 0)) {
                throw new \Exception("Pelanggan tidak ditemukan atau non-aktif.");
            }

            // 2. CEK KREDIT MENGGUNAKAN HELPER TERPUSAT DI MODEL SALESORDER
            $isCreditHold = false;
            $catatanKredit = '';

            if ($backendPaymentMethod === 'kredit') {
                $creditCheck = SalesOrder::checkCreditHold($customer->id, $calc['grand_total']);
                
                // Minta bantuan mesin Auto-Grading
                $grade = $this->_calculateCustomerGrade($customer->id);
                $isGradeHold = in_array($grade, ['B', 'C', 'D']); 

                if ($creditCheck['is_hold'] || $isGradeHold) {
                    $isCreditHold = true;
                    
                    $reasons = [];
                    if ($creditCheck['is_hold']) $reasons[] = $creditCheck['message'];
                    if ($isGradeHold) $reasons[] = "Pelanggan Grade $grade (Ada histori telat bayar > 30 hari dalam 3 bln terakhir)";
                    
                    $catatanKredit = "\n[" . implode(" | ", $reasons) . "]";
                }
            }

            $finalDueDays = $backendPaymentMethod === 'kredit' ? (int)($customer->due_days ?? 0) : 0;
            $dueDate = $finalDueDays > 0 ? Carbon::today()->addDays($finalDueDays)->toDateString() : null;

            $totalCogs = 0;
            $stockUpdates = [];
            $accumulatedRequirements = [];

            // 3. PREPARASI & KALKULASI KONVERSI ITEM UTAMA
            foreach ($calc['items'] as $item) {
                $product = DB::table('products')->where('id', $item['product_id'])->first();
                $multiplier = 1;
                $uName = strtoupper(trim($item['unit']));
                
                if ($uName === strtoupper(trim($product->buy_unit ?? ''))) $multiplier = $product->conversion_factor ?? 1;
                elseif ($uName === strtoupper(trim($product->unit_3_name ?? ''))) $multiplier = $product->conversion_3_qty ?? 1;
                elseif ($uName === strtoupper(trim($product->unit_4_name ?? ''))) $multiplier = $product->conversion_4_qty ?? 1;
                
                $totalBaseQty = $item['qty'] * $multiplier;
                $hpp = (isset($product->average_cost) && $product->average_cost > 0) ? (float) $product->average_cost : (float) ($product->buy_price ?? 0);
                $totalCogs += ($hpp * $totalBaseQty);

                if (!isset($accumulatedRequirements[$item['product_id']])) $accumulatedRequirements[$item['product_id']] = 0;
                $accumulatedRequirements[$item['product_id']] += $totalBaseQty;

                $stockUpdates[] = [
                    'product_id' => $item['product_id'],
                    'qty_load' => $item['qty'],
                    'total_base_qty' => $totalBaseQty,
                    'unit_name' => $item['unit']
                ];
            }

            // 4. PREPARASI ITEM BONUS
            foreach ($calc['bonus_items'] as $bonus) {
                $product = DB::table('products')->where('id', $bonus['product_id'])->first();
                $multiplier = 1;
                $uName = strtoupper(trim($bonus['unit']));
                
                if ($uName === strtoupper(trim($product->buy_unit ?? ''))) $multiplier = $product->conversion_factor ?? 1;
                elseif ($uName === strtoupper(trim($product->unit_3_name ?? ''))) $multiplier = $product->conversion_3_qty ?? 1;
                elseif ($uName === strtoupper(trim($product->unit_4_name ?? ''))) $multiplier = $product->conversion_4_qty ?? 1;

                $totalBaseQty = $bonus['qty'] * $multiplier;
                $hpp = (isset($product->average_cost) && $product->average_cost > 0) ? (float) $product->average_cost : (float) ($product->buy_price ?? 0);
                $totalCogs += ($hpp * $totalBaseQty);

                if (!isset($accumulatedRequirements[$bonus['product_id']])) $accumulatedRequirements[$bonus['product_id']] = 0;
                $accumulatedRequirements[$bonus['product_id']] += $totalBaseQty;

                $stockUpdates[] = [
                    'product_id' => $bonus['product_id'],
                    'qty_load' => $bonus['qty'],
                    'total_base_qty' => $totalBaseQty,
                    'unit_name' => $bonus['unit']
                ];
            }

            // 5. VALIDASI STOK KANVAS (LOCK FOR UPDATE) - Hanya Jika Lolos Kredit
            if (!$isCreditHold) {
                foreach ($accumulatedRequirements as $productId => $totalNeededQty) {
                    $cStock = CanvasStock::where('salesman_id', $salesman->id)
                                ->where('product_id', $productId)
                                ->lockForUpdate() // Kunci stok agar tidak keduluan order lain
                                ->first();

                    if (!$cStock || $totalNeededQty > $cStock->quantity) {
                         $avail = $cStock ? $cStock->quantity : 0;
                         $prodName = DB::table('products')->where('id', $productId)->value('name');
                         throw new \Exception("Gagal! Stok Kanvas untuk {$prodName} tidak mencukupi. Butuh: {$totalNeededQty}, Tersedia: {$avail}.");
                    }
                }
            }

            $soNumber = 'SO-CNV-' . date('Ymd') . '-' . rand(1000, 9999);
            $invoiceNumber = str_replace('SO-', 'INV-', $soNumber); // Dideklarasikan di luar if agar global
            
            // PERBAIKAN LOGIKA STATUS SO:
            // Jika kredit -> completed (masuk piutang). 
            // Jika tunai -> selesai (barang diterima, kas ditahan di akun titipan menunggu disetor Finance).
            $orderStatus = $isCreditHold 
                ? SalesOrder::STATUS_PENDING_APPROVAL 
                : ($backendPaymentMethod === 'cash' ? 'selesai' : SalesOrder::STATUS_COMPLETED);
            
            // 6. SIMPAN DRAF PESANAN (SALES ORDER)
            $soId = DB::table('sales_orders')->insertGetId([
                'so_number' => $soNumber,
                'branch_id' => $branchId, 
                'fulfillment_branch_id' => $branchId,
                'customer_id' => $customer->id,
                'salesman_id' => $salesman->id, 
                'user_id' => $userId,
                'customer_name' => $customer->name,
                'customer_phone' => $customer->phone,
                'shipping_address' => $customer->address,
                'subtotal' => $calc['subtotal'],
                'discount_amount' => $calc['discount_amount'],
                'grand_total' => $calc['grand_total'],
                'payment_method' => $backendPaymentMethod,
                'due_days' => $finalDueDays, 
                'status' => $orderStatus,
                'note' => 'Penjualan Kanvas' . $catatanKredit,
                'delivery_date' => Carbon::today(),
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now(),
            ]);

            // 7. SIMPAN FAKTUR (SALES)
            $saleId = DB::table('sales')->insertGetId([
                'sales_order_id' => $soId,
                'branch_id' => $branchId,
                'user_id' => $userId, 
                'customer_id' => $customer->id,
                'customer_name' => $customer->name,
                'invoice_number' => $invoiceNumber,
                'subtotal' => $calc['subtotal'],
                'tax_amount' => $calc['tax_amount'], 
                'discount_amount' => $calc['discount_amount'], 
                'grand_total' => $calc['grand_total'], 
                'payment_method' => $backendPaymentMethod,
                'payment_status' => $isCreditHold ? SalesOrder::STATUS_PENDING_APPROVAL : ($backendPaymentMethod === 'cash' ? 'paid' : 'unpaid'),
                'paid_amount' => ($backendPaymentMethod === 'cash' && !$isCreditHold) ? $calc['grand_total'] : 0, 
                'delivery_status' => 'selesai',
                'delivery_date' => Carbon::today(),
                'due_date' => $dueDate,
                'due_days' => $finalDueDays, 
                'print_count' => 1, 
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now(),
            ]);

            // 8. SIMPAN ITEM
            foreach ($calc['items'] as $item) {
                DB::table('sale_items')->insert([
                    'sale_id' => $saleId,
                    'product_id' => $item['product_id'],
                    'product_name' => $item['product_name'],
                    'unit' => $item['unit'],
                    'quantity' => $item['qty'],
                    'unit_price' => $item['qty'] > 0 ? ($item['total_price'] / $item['qty']) : 0, 
                    'total_price' => $item['total_price'],
                    'base_conversion_factor' => 1,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now()
                ]);
            }

            foreach ($calc['bonus_items'] as $bonus) {
                DB::table('sale_items')->insert([
                    'sale_id' => $saleId,
                    'product_id' => $bonus['product_id'],
                    'product_name' => $bonus['product_name'],
                    'unit' => $bonus['unit'],
                    'quantity' => $bonus['qty'],
                    'unit_price' => 0, 
                    'total_price' => 0,
                    'base_conversion_factor' => 1,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now()
                ]);
            }

            // ========================================================================
            // 9. CABANG EKSEKUSI NYATA (JURNAL & STOK) HANYA JIKA TIDAK HOLD
            // ========================================================================
            if (!$isCreditHold) {
                foreach ($stockUpdates as $st) {
                    CanvasStock::where('salesman_id', $salesman->id)
                        ->where('product_id', $st['product_id'])
                        ->decrement('quantity', $st['total_base_qty']);

                    DB::table('stock_transactions')->insert([
                        'branch_id' => $branchId,
                        'product_id' => $st['product_id'],
                        'type' => 'sale_canvas',
                        'input_quantity' => -$st['qty_load'],
                        'input_unit' => $st['unit_name'],
                        'actual_quantity' => -$st['total_base_qty'],
                        'user_id' => $userId,
                        'note' => 'Penjualan Kanvas (SJ: ' . $invoiceNumber . ')',
                        'created_at' => Carbon::now(),
                        'updated_at' => Carbon::now()
                    ]);
                }

                $accReceivable = AccountingService::getAccountId('receivable_account');
                $accSalesRevenue = AccountingService::getAccountId('sales_revenue_account');
                $accPpnOutput = AccountingService::getAccountId('ppn_output_account');
                $accCostOfGoodsSold = AccountingService::getAccountId('cost_of_goods_sold_account');
                $accInventory = AccountingService::getAccountId('inventory_account');
                $accCashSales = AccountingService::getAccountId('cash_sales_account'); 

                if ($accReceivable && $accSalesRevenue && $accCostOfGoodsSold && $accInventory && $accCashSales) {
                    $debitAccount = $backendPaymentMethod === 'cash' ? $accCashSales : $accReceivable;

                    $journalItems = [];
                    $journalItems[] = ['account_id' => $debitAccount, 'debit' => $calc['grand_total'], 'credit' => 0];
                    if ($calc['tax_amount'] > 0) {
                        $journalItems[] = ['account_id' => $accPpnOutput, 'debit' => 0, 'credit' => $calc['tax_amount']];
                    }
                    $journalItems[] = ['account_id' => $accSalesRevenue, 'debit' => 0, 'credit' => $calc['dpp']];
                    $journalItems[] = ['account_id' => $accCostOfGoodsSold, 'debit' => $totalCogs, 'credit' => 0];
                    $journalItems[] = ['account_id' => $accInventory, 'debit' => 0, 'credit' => $totalCogs];

                    AccountingService::log([
                        'branch_id'   => $branchId,
                        'entry_date'  => Carbon::today()->toDateString(),
                        'description' => 'Penjualan Kanvas ' . $invoiceNumber . ' (' . $customer->name . ')',
                        'reference'   => $invoiceNumber,
                        'source_type' => 'SALES_CANVAS',
                        'user_id'     => $userId,
                        'items'       => $journalItems
                    ]);
                }
            }

            if ($request->filled('visit_id')) {
                DB::table('salesman_visits')->where('id', $request->visit_id)->update([
                    'visit_result' => 'order',
                    'updated_at' => Carbon::now()
                ]);
            }

            DB::commit();

            return response()->json([
                'success' => true,
                'message' => $isCreditHold 
                    ? "PERINGATAN: Pelanggan Grade Berisiko atau OVERLIMIT. Penjualan Kanvas ditahan dan menunggu Otorisasi Pusat."
                    : "Pesanan Kanvas berhasil disimpan & Faktur resmi telah diterbitkan.",
                'invoice_number' => $invoiceNumber
            ]);

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

    /**
     * ========================================================================
     * GET HISTORY KANVAS (ENDPOINT BARU UNTUK HALAMAN RIWAYAT)
     * ========================================================================
     */
    public function getHistory(Request $request)
    {
        try {
            $user = $request->user();
            $branchId = $user->role === 'owner' ? ($request->query('branch_id') ?? $user->branch_id) : $user->branch_id;

            $query = DB::table('sales_orders')
                ->leftJoin('sales', 'sales_orders.id', '=', 'sales.sales_order_id')
                ->leftJoin('salesmen', 'sales_orders.salesman_id', '=', 'salesmen.id')
                ->leftJoin('users as salesman_user', 'salesmen.user_id', '=', 'salesman_user.id')
                ->where('sales_orders.so_number', 'like', 'SO-CNV-%')
                ->select(
                    'sales_orders.id',
                    'sales_orders.so_number',
                    'sales_orders.customer_name',
                    'sales_orders.grand_total',
                    'sales_orders.status',
                    'sales_orders.payment_method',
                    'sales_orders.created_at',
                    'sales_orders.note',
                    'sales.invoice_number',
                    'sales.payment_status',
                    'salesman_user.name as salesman_name'
                );

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

            $history = $query->orderBy('sales_orders.created_at', 'desc')->get();

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

    /**
     * ========================================================================
     * FUNGSI VOID TRANSAKSI KANVAS (DENGAN REVERSAL JURNAL DAN STOK)
     * ========================================================================
     */
    public function voidOrder(Request $request, $id)
    {
        $request->validate([
            'reason' => 'required|string'
        ]);

        $userId = auth()->id();

        DB::beginTransaction();
        try {
            // 1. Kunci data Sales Order
            $order = DB::table('sales_orders')->where('id', $id)->lockForUpdate()->first();
            if (!$order) throw new \Exception("Transaksi tidak ditemukan.");
            if (in_array($order->status, ['void', 'cancelled'])) throw new \Exception("Gagal! Transaksi sudah dibatalkan sebelumnya.");

            // Cari data Faktur (Sales) terkait
            $sale = DB::table('sales')->where('sales_order_id', $order->id)->lockForUpdate()->first();
            if (!$sale) throw new \Exception("Data Faktur tidak ditemukan untuk referensi SO ini.");

            $totalCogs = 0;

            // 2. Balikkan Stok Kanvas (Increment kembali) & Hitung Ulang HPP
            if ($order->status !== 'pending_approval' && $order->status !== 'credit_hold') {
                $items = DB::table('sale_items')->where('sale_id', $sale->id)->get();
                foreach ($items as $item) {
                    $actualQty = $item->quantity * $item->base_conversion_factor;

                    $product = DB::table('products')->where('id', $item->product_id)->first();
                    if ($product) {
                        $hpp = (isset($product->average_cost) && $product->average_cost > 0) ? (float) $product->average_cost : (float) ($product->buy_price ?? 0);
                        $totalCogs += ($hpp * $actualQty);
                    }

                    CanvasStock::where('salesman_id', $order->salesman_id)
                        ->where('product_id', $item->product_id)
                        ->increment('quantity', $actualQty); 

                    DB::table('stock_transactions')->insert([
                        'branch_id' => $sale->branch_id,
                        'product_id' => $item->product_id,
                        'type' => 'sale_canvas_void',
                        'input_quantity' => $item->quantity,
                        'input_unit' => $item->unit,
                        'actual_quantity' => $actualQty,
                        'user_id' => $userId, 
                        'note' => 'VOID Kanvas (SJ: ' . $sale->invoice_number . ') - ' . $request->reason,
                        'created_at' => Carbon::now(),
                        'updated_at' => Carbon::now()
                    ]);
                }
            }

            // 3. Buat Jurnal Pembalik (Reversing Entry)
            if ($order->status !== 'pending_approval' && $order->status !== 'credit_hold') {
                $accReceivable = AccountingService::getAccountId('receivable_account');
                $accSalesRevenue = AccountingService::getAccountId('sales_revenue_account');
                $accPpnOutput = AccountingService::getAccountId('ppn_output_account');
                $accCostOfGoodsSold = AccountingService::getAccountId('cost_of_goods_sold_account');
                $accInventory = AccountingService::getAccountId('inventory_account');
                $accCashSales = AccountingService::getAccountId('cash_sales_account'); 

                if ($accReceivable && $accSalesRevenue && $accCostOfGoodsSold && $accInventory && $accCashSales) {
                    $debitAccount = $sale->payment_method === 'cash' ? $accCashSales : $accReceivable;
                    
                    $dpp = $sale->grand_total - ($sale->tax_amount ?? 0);

                    $reversalItems = [];
                    $reversalItems[] = ['account_id' => $debitAccount, 'debit' => 0, 'credit' => $sale->grand_total];
                    if ($sale->tax_amount > 0) {
                        $reversalItems[] = ['account_id' => $accPpnOutput, 'debit' => $sale->tax_amount, 'credit' => 0];
                    }
                    $reversalItems[] = ['account_id' => $accSalesRevenue, 'debit' => $dpp, 'credit' => 0];
                    $reversalItems[] = ['account_id' => $accCostOfGoodsSold, 'debit' => 0, 'credit' => $totalCogs];
                    $reversalItems[] = ['account_id' => $accInventory, 'debit' => $totalCogs, 'credit' => 0];

                    AccountingService::log([
                        'branch_id'   => $sale->branch_id,
                        'entry_date'  => Carbon::today()->toDateString(),
                        'description' => 'VOID Penjualan Kanvas ' . $sale->invoice_number . ' (' . $sale->customer_name . ')',
                        'reference'   => $sale->invoice_number . '-VOID',
                        'source_type' => 'SALE_CANVAS_VOID',
                        'user_id'     => $userId,
                        'items'       => $reversalItems
                    ]);
                }
            }

            DB::table('sales_orders')->where('id', $order->id)->update([
                'status' => 'void', 
                'note' => $order->note . "\n[VOID: " . $request->reason . "]",
                'updated_at' => Carbon::now()
            ]);
            
            DB::table('sales')->where('id', $sale->id)->update([
                'delivery_status' => 'void',
                'payment_status' => 'void', 
                'updated_at' => Carbon::now()
            ]);

            DB::commit();
            return response()->json([
                'success' => true, 
                'message' => 'Transaksi berhasil dibatalkan (VOID). Stok mobil dan jurnal akuntansi telah dinetralkan.'
            ]);

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