<?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 Carbon\Carbon;
use App\Services\AccountingService;

class CanvasLoadingController extends Controller
{
    public function getAvailableProducts(Request $request)
    {
        try {
            $user = auth()->user();
            // Owner bisa melihat stok cabang tertentu jika mengirimkan branch_id, jika tidak gunakan branch_id user
            $branchId = ($user->role === 'owner' && $request->filled('branch_id')) 
                        ? $request->branch_id 
                        : ($user->branch_id ?? 1);
            
            $products = DB::table('products as p')
                ->join('product_stocks as ps', 'p.id', '=', 'ps.product_id')
                ->where('ps.branch_id', $branchId)
                ->where('p.is_active', 1)
                ->whereIn('product_type', ['trading', 'finished_good'])
                ->select('p.id', 'p.name', 'p.variant_name', 'p.unit', 'p.buy_unit', 'p.unit_3_name', 'p.unit_4_name', 'p.conversion_factor', 'p.conversion_3_qty', 'p.conversion_4_qty')
                ->get();

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

    public function store(Request $request)
    {
        $request->validate([
            'salesman_id' => 'required|exists:salesmen,id',
            'items' => 'required|array',
            'items.*.product_id' => 'required|exists:products,id',
            'items.*.quantity' => 'required|numeric|min:0.01',
            'items.*.unit' => 'required|string',
            'branch_id' => 'nullable|exists:branches,id'
        ]);

        $user = auth()->user();
        $userId = $user->id;
        
        $branchId = ($user->role === 'owner' && $request->filled('branch_id')) 
                    ? $request->branch_id 
                    : ($user->branch_id ?? 1);

        // PENAMBAHAN: Proteksi Pembajakan Salesman Lintas Cabang
        if ($user->role !== 'owner') {
            $salesmanData = DB::table('salesmen')
                ->join('users', 'salesmen.user_id', '=', 'users.id')
                ->where('salesmen.id', $request->salesman_id)
                ->select('users.branch_id')
                ->first();
                
            if ($salesmanData && $salesmanData->branch_id !== $branchId) {
                return response()->json([
                    'success' => false, 
                    'message' => 'Akses ditolak: Salesman yang dipilih bukan armada dari cabang Anda.'
                ], 403);
            }
        }

        DB::beginTransaction();
        try {
            $loading = CanvasLoading::create([
                'salesman_id' => $request->salesman_id,
                'branch_id' => $branchId, 
                'date' => Carbon::today(),
                'status' => 'approved',
                'created_by' => $userId
            ]);

            foreach ($request->items as $item) {
                $product = DB::table('products')->where('id', $item['product_id'])->first();
                
                // Kalkulasi konversi ke base unit
                $multiplier = 1;
                $u = strtoupper(trim($item['unit']));
                if ($u === strtoupper(trim($product->buy_unit ?? ''))) $multiplier = $product->conversion_factor ?? 1;
                elseif ($u === strtoupper(trim($product->unit_3_name ?? ''))) $multiplier = $product->conversion_3_qty ?? 1;
                elseif ($u === strtoupper(trim($product->unit_4_name ?? ''))) $multiplier = $product->conversion_4_qty ?? 1;

                $totalBaseQty = (float)$item['quantity'] * $multiplier;

                // VALIDASI STOK SEBELUM DECREMENT
                $stock = DB::table('product_stocks')
                    ->where('branch_id', $branchId)
                    ->where('product_id', $item['product_id'])
                    ->lockForUpdate()
                    ->first();

                if (!$stock || $stock->quantity < $totalBaseQty) {
                    throw new \Exception("Stok tidak mencukupi untuk produk: " . $product->name);
                }

                // Potong stok pusat
                DB::table('product_stocks')
                    ->where('branch_id', $branchId)
                    ->where('product_id', $item['product_id'])
                    ->decrement('quantity', $totalBaseQty);

                // Tambah stok kanvas
                CanvasStock::updateOrCreate(
                    ['salesman_id' => $request->salesman_id, 'product_id' => $item['product_id'], 'branch_id' => $branchId],
                    ['quantity' => DB::raw('quantity + ' . $totalBaseQty)]
                );

                CanvasLoadingItem::create([
                    'canvas_loading_id' => $loading->id,
                    'product_id' => $item['product_id'],
                    'quantity' => $totalBaseQty,
                    'unit' => $item['unit'] 
                ]);
            }

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

    public function index()
    {
        try {
            $user = auth()->user();
            
            // PERBAIKAN: Menambahkan 'branch' ke dalam array with() agar data cabang ikut ditarik
            $query = CanvasLoading::with(['salesman.user', 'items.product', 'branch'])
                ->orderBy('date', 'desc');

            // PENAMBAHAN: Filter Cabang
            if ($user && $user->role !== 'owner') {
                $query->where('branch_id', $user->branch_id);
            }

            $loadings = $query->get();
                
            // Kalkulasi otomatis qty_invoiced untuk dokumen yang siap di-settle finance
            foreach ($loadings as $loading) {
                if ($loading->status === 'unloaded' || $loading->status === 'settled') {
                    
                    foreach ($loading->items as $item) {
                        // JOIN 3 Tabel: sale_items -> sales -> sales_orders
                        $invoicedQty = DB::table('sale_items')
                            ->join('sales', 'sales.id', '=', 'sale_items.sale_id')
                            ->join('sales_orders', 'sales_orders.id', '=', 'sales.sales_order_id')
                            ->where('sales_orders.salesman_id', $loading->salesman_id)
                            ->whereDate('sales.created_at', $loading->date)
                            ->where('sale_items.product_id', $item->product_id)
                            ->where('sales_orders.status', '!=', 'void')
                            ->sum('sale_items.quantity');
                            
                        $item->qty_invoiced = (float)$invoicedQty;
                    }
                }
            }
                
            return response()->json(['success' => true, 'data' => $loadings]);
        } catch (\Exception $e) {
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function void($id)
    {
        DB::beginTransaction();
        try {
            $user = auth()->user();
            $loading = CanvasLoading::with('items')->findOrFail($id);

            if ($user && $user->role !== 'owner' && $loading->branch_id !== $user->branch_id) {
                throw new \Exception("Akses ditolak: Anda tidak memiliki hak akses untuk membatalkan dokumen cabang lain.");
            }

            if ($loading->status === 'void') {
                throw new \Exception("Pemuatan ini sudah dibatalkan sebelumnya.");
            }

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

            // Kembalikan stok ke gudang pusat & kurangi stok dari kanvas
            foreach ($loading->items as $item) {
                DB::table('product_stocks')
                    ->where('branch_id', $branchId)
                    ->where('product_id', $item->product_id)
                    ->increment('quantity', $item->quantity);

                CanvasStock::where('salesman_id', $loading->salesman_id)
                    ->where('product_id', $item->product_id)
                    ->decrement('quantity', $item->quantity);
            }

            $loading->update(['status' => 'void']);

            DB::commit();
            return response()->json(['success' => true, 'message' => 'Pemuatan berhasil dibatalkan.']);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    /**
     * TAHAP C: SETTLEMENT FINANCE & PENJURNALAN (CLOSING)
     */
    public function settleCanvas(Request $request, $id)
    {
        DB::beginTransaction();
        try {
            $user = auth()->user();
            $loading = CanvasLoading::with('salesman.user')->findOrFail($id);

            if ($user && $user->role !== 'owner' && $loading->branch_id !== $user->branch_id) {
                throw new \Exception("Akses ditolak: Anda tidak memiliki hak akses untuk melakukan settlement dokumen cabang lain.");
            }

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

            if ($loading->status !== 'unloaded') {
                throw new \Exception("Dokumen belum di-Unload oleh Gudang. Selesaikan Tahap A terlebih dahulu.");
            }

            // PERBAIKAN FATAL: Menarik ID Akun dari konfigurasi Enterprise, menghindari penggunaan "Kode Akun" sebagai "ID"
            $coaBebanSelisihId = AccountingService::getAccountId('canvas_loss_account') 
                                 ?? DB::table('accounts')->where('code', 'like', '6%')->where('name', 'like', '%Selisih%')->value('id');
            
            $coaPersediaanId = AccountingService::getAccountId('inventory_account') 
                               ?? DB::table('accounts')->where('code', 'like', '11%')->where('name', 'like', '%Persediaan%')->value('id');

            if (!$coaBebanSelisihId || !$coaPersediaanId) {
                throw new \Exception("Akun Beban Selisih atau Akun Persediaan belum dipetakan secara global. Harap hubungi Pusat.");
            }

            $totalLossAmount = 0;
            $loadingItems = CanvasLoadingItem::where('canvas_loading_id', $id)->get();

            foreach ($loadingItems as $loadingItem) {
                $productId = $loadingItem->product_id;
                
                $product = DB::table('products')->where('id', $productId)->first();
                $hpp = $product ? (float)$product->buy_price : 0;

                // 1. Ambil Sisa Fisik (dari Tahap A atau Hasil Revisi)
                $qtySoldPhysical = (float)$loadingItem->qty_sold; 
                
                // 2. Tarik Paksa Data Faktur dari 3 Tabel
                $qtyInvoiced = (float) DB::table('sale_items')
                    ->join('sales', 'sales.id', '=', 'sale_items.sale_id')
                    ->join('sales_orders', 'sales_orders.id', '=', 'sales.sales_order_id')
                    ->where('sales_orders.salesman_id', $loading->salesman_id)
                    ->whereDate('sales.created_at', $loading->date)
                    ->where('sale_items.product_id', $productId)
                    ->where('sales_orders.status', '!=', 'void')
                    ->sum('sale_items.quantity');

                // 3. Selisih = Barang yang keluar fisik TAPI tidak ada fakturnya
                $selisihHilang = $qtySoldPhysical - $qtyInvoiced; 

                // Jika ada barang hilang, catat kerugian HPP
                if ($selisihHilang > 0) {
                    $lossValue = $selisihHilang * $hpp;
                    $totalLossAmount += $lossValue;

                    DB::table('stock_adjustments')->insert([
                        'product_id' => $productId,
                        'branch_id' => $branchId,
                        'quantity' => 0, 
                        'reason' => 'Finance Audit: Selisih ' . $selisihHilang . ' pcs tidak berfaktur. Sales: ' . $loading->salesman_id,
                        'created_at' => \Carbon\Carbon::now(),
                        'updated_at' => \Carbon\Carbon::now()
                    ]);
                }
                
                // 4. Update kolom faktur riil untuk arsip
                $loadingItem->update([
                    'qty_invoiced' => $qtyInvoiced
                ]);
            }

            // JURNALISASI OTOMATIS MENGGUNAKAN ACCOUNTING SERVICE
            if ($totalLossAmount > 0) {
                $salesName = ($loading->salesman && $loading->salesman->user) ? $loading->salesman->user->name : 'Unknown Salesman';
                
                AccountingService::log([
                    'branch_id'   => $branchId,
                    'entry_date'  => \Carbon\Carbon::now()->toDateString(),
                    'description' => 'Tanggungan Piutang Selisih Kanvas - Sales: ' . $salesName,
                    'source_type' => 'canvas_settlement',
                    'reference'   => 'JRN-CNV-' . date('ymd') . '-' . mt_rand(1000, 9999),
                    'user_id'     => auth()->id(),
                    'items'       => [
                        [
                            'account_id' => $coaBebanSelisihId, // DEBET (Piutang/Beban)
                            'debit'      => $totalLossAmount,
                            'credit'     => 0,
                        ],
                        [
                            'account_id' => $coaPersediaanId,   // KREDIT (Persediaan Keluar)
                            'debit'      => 0,
                            'credit'     => $totalLossAmount,
                        ]
                    ]
                ]);
            }

            // Tahap Final: Tutup dokumen
            $loading->update(['status' => 'settled', 'settled_at' => \Carbon\Carbon::now()]);

            DB::commit();
            return response()->json([
                'success' => true, 
                'message' => 'Settlement Finance berhasil diproses.',
                'total_loss_value' => $totalLossAmount
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    public function print($id)
    {
        $user = auth()->user();
        $data = CanvasLoading::with(['items.product', 'salesman.user'])->findOrFail($id);
        
        if ($user && $user->role !== 'owner' && $data->branch_id !== $user->branch_id) {
            abort(403, 'Akses ditolak.');
        }

        return view('print.canvas_loading', compact('data')); 
    }

    /**
     * TAHAP A: UNLOADING FISIK (TUGAS GUDANG SORE HARI)
     */
    public function unloadCanvas(Request $request, $id)
    {
        $itemsReturned = $request->items; 

        DB::beginTransaction();
        try {
            $user = auth()->user();
            $loading = CanvasLoading::findOrFail($id);

            if ($user && $user->role !== 'owner' && $loading->branch_id !== $user->branch_id) {
                throw new \Exception("Akses ditolak: Anda tidak memiliki hak akses untuk membongkar dokumen cabang lain.");
            }

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

            if ($loading->status !== 'approved') {
                throw new \Exception("Hanya dokumen berstatus 'approved' (Sedang Kanvas) yang bisa di-Unload.");
            }

            foreach ($itemsReturned as $item) {
                $productId = $item['product_id'];
                $fisikKembali = (float)$item['qty_returned'];

                $loadingItem = CanvasLoadingItem::where('canvas_loading_id', $id)
                                                ->where('product_id', $productId)
                                                ->first();
                
                if(!$loadingItem) continue;

                $bawaPagi = (float)$loadingItem->quantity; 
                $terjualBaru = $bawaPagi - $fisikKembali;
                
                $loadingItem->update([
                    'qty_returned' => $fisikKembali,
                    'qty_sold' => $terjualBaru >= 0 ? $terjualBaru : 0
                ]);

                // 2. Mutasi fisik SAH kembali ke gudang asal
                if ($fisikKembali > 0) {
                    DB::table('product_stocks')
                        ->where('branch_id', $branchId)
                        ->where('product_id', $productId)
                        ->increment('quantity', $fisikKembali);
                }

                // 3. Kurangi stok dari tangan salesman
                $canvasStock = CanvasStock::where('salesman_id', $loading->salesman_id)
                                          ->where('product_id', $productId)
                                          ->first();
                if ($canvasStock) {
                    $canvasStock->decrement('quantity', $fisikKembali);
                }
            }

            $loading->update(['status' => 'unloaded']);

            DB::commit();
            return response()->json([
                'success' => true, 
                'message' => 'Bongkar muat fisik selesai. Stok gudang utama telah bertambah.'
            ]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    /**
     * FITUR KOREKSI: REVISI FISIK OLEH SUPERVISOR
     */
    public function revisePhysicalCount(Request $request, $id)
    {
        $request->validate([
            'product_id' => 'required|exists:products,id',
            'new_qty_returned' => 'required|numeric|min:0',
            'supervisor_email' => 'required|string',
            'supervisor_password' => 'required|string'
        ]);

        DB::beginTransaction();
        try {
            // 1. Verifikasi Supervisor
            $supervisor = \App\Models\User::where('email', $request->supervisor_email)->first();
            if (!$supervisor || !\Illuminate\Support\Facades\Hash::check($request->supervisor_password, $supervisor->password)) {
                throw new \Exception("Otorisasi Gagal: Kredensial supervisor salah.");
            }

            // Ambil data loading secara manual 
            $loading = \DB::table('canvas_loadings')->where('id', $id)->first();
            if (!$loading) {
                throw new \Exception("Data loading tidak ditemukan.");
            }

            // Pastikan supervisor hanya bisa merevisi cabang miliknya sendiri (kecuali owner)
            if ($supervisor->role !== 'owner' && $loading->branch_id !== $supervisor->branch_id) {
                throw new \Exception("Otorisasi Gagal: Supervisor ini tidak memiliki wewenang untuk cabang dokumen ini.");
            }

            // 2. Ambil data item kanvas
            $loadingItem = \App\Models\CanvasLoadingItem::where('canvas_loading_id', $id)
                ->where('product_id', $request->product_id)
                ->firstOrFail();

            // 4. Hitung Delta
            $oldQty = (float)$loadingItem->qty_returned;
            $newQty = (float)$request->new_qty_returned;
            
            // Delta adalah selisih antara koreksi fisik baru dikurangi perhitungan fisik lama.
            $delta = $newQty - $oldQty;

            // 5. Update data kanvas
            $loadingItem->update([
                'qty_returned' => $newQty,
                'qty_sold' => (float)$loadingItem->quantity - $newQty
            ]);

            // 6. PERBAIKAN LOGIKA MATEMATIKA: Mutasi Stok Langsung
            // Jika delta positif (Barang kembali LEBIH BANYAK dari dugaan awal), maka Gudang Pusat bertambah, Kanvas berkurang.
            // Jika delta negatif (Barang kembali LEBIH SEDIKIT dari dugaan awal), maka Gudang Pusat berkurang, Kanvas bertambah.
            if ($delta != 0) {
                \DB::table('product_stocks')
                    ->where('branch_id', $loading->branch_id ?? 1) 
                    ->where('product_id', $request->product_id)
                    ->increment('quantity', $delta); // Mengembalikan lebih banyak = gudang bertambah

                \DB::table('canvas_stocks')
                    ->where('salesman_id', $loading->salesman_id)
                    ->where('product_id', $request->product_id)
                    ->decrement('quantity', $delta); // Mengembalikan lebih banyak = stok tangan salesman ditarik
            }

            DB::commit();
            return response()->json(['success' => true, 'message' => 'Revisi fisik selesai. Stok telah disesuaikan secara langsung.']);
            
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => $e->getMessage()], 400);
        }
    }
}