<?php

namespace App\Http\Controllers\Api;

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

class StockTransferController extends Controller
{
    /**
     * Menampilkan daftar mutasi stok dengan join cabang
     */
    public function index(Request $request)
    {
        try {
            $user = auth()->user();

            $query = DB::table('stock_transfers as st')
                ->join('branches as fb', 'st.from_branch_id', '=', 'fb.id')
                ->join('branches as tb', 'st.to_branch_id', '=', 'tb.id')
                ->select(
                    'st.*', 
                    'fb.name as from_branch_name', 
                    'tb.name as to_branch_name'
                );

            // PERBAIKAN ENTERPRISE: Isolasi Daftar Mutasi (Hanya yang terkait dengan cabangnya, baik Asal maupun Tujuan)
            if ($user && $user->role !== 'owner') {
                $query->where(function($q) use ($user) {
                    $q->where('st.from_branch_id', $user->branch_id)
                      ->orWhere('st.to_branch_id', $user->branch_id);
                });
            }

            $query->orderBy('st.created_at', 'desc');

            return response()->json([
                'success' => true,
                'data' => $query->get() 
            ]);
        } catch (\Exception $e) {
            Log::error("Load Transfer List Error: " . $e->getMessage());
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    /**
     * Mengambil detail mutasi untuk kebutuhan CETAK ULANG (Reprint)
     */
    public function show($id)
    {
        try {
            $user = auth()->user();

            $transfer = DB::table('stock_transfers as st')
                ->join('branches as fb', 'st.from_branch_id', '=', 'fb.id')
                ->join('branches as tb', 'st.to_branch_id', '=', 'tb.id')
                ->select('st.*', 'fb.name as from_branch_name', 'tb.name as to_branch_name')
                ->where('st.id', $id)
                ->first();

            if (!$transfer) {
                return response()->json(['success' => false, 'message' => 'Data mutasi tidak ditemukan'], 404);
            }

            // PERBAIKAN ENTERPRISE: Proteksi IDOR Detail Mutasi
            if ($user && $user->role !== 'owner') {
                if ($transfer->from_branch_id !== $user->branch_id && $transfer->to_branch_id !== $user->branch_id) {
                    return response()->json(['success' => false, 'message' => 'Akses ditolak: Dokumen mutasi ini bukan wewenang cabang Anda.'], 403);
                }
            }

            $items = DB::table('stock_transfer_items as sti')
                ->join('products as p', 'sti.product_id', '=', 'p.id')
                ->select('sti.*', 'p.name', 'p.sku', 'p.unit')
                ->where('sti.stock_transfer_id', $id)
                ->whereNotIn('p.product_type', ['raw_material', 'consumable']) // Pastikan tipe produk yang tidak diinginkan tidak muncul
                ->get();

            return response()->json([
                'success' => true,
                'data' => $transfer,
                'items' => $items
            ]);
        } catch (\Exception $e) {
            Log::error("Load Transfer Detail Error: " . $e->getMessage());
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    /**
     * Mengambil daftar produk khusus mutasi (4 level satuan)
     */
    public function getTransferProducts(Request $request)
    {
        try {
            $products = DB::table('products')
                ->where('is_active', 1)
                ->whereIn('product_type', ['trading', 'finished_good'])
                ->select(
                    'id', 'sku', 'name', 
                    'unit', 'buy_unit', 'unit_3_name', 'unit_4_name', 
                    'variant_group_id', 'variant_name', 'buy_price'
                )
                ->orderBy('name', 'asc')
                ->get();

            return response()->json([
                'success' => true,
                'data' => $products
            ]);
        } catch (\Exception $e) {
            Log::error("Load Transfer Products Error: " . $e->getMessage());
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    /**
     * Simpan transaksi mutasi (Workflow: Transit -> Kurangi Stok Asal -> Jurnal)
     */
    public function store(Request $request)
    {
        $request->validate([
            'from_branch_id' => 'required',
            'to_branch_id' => 'required|different:from_branch_id',
            'transfer_date' => 'required|date',
            'notes' => 'nullable|string',
            'items' => 'required|array|min:1',
            'items.*.product_id' => 'required',
            'items.*.qty' => 'required|numeric|min:1',
        ]);

        try {
            return DB::transaction(function () use ($request) {
                $user = auth()->user();

                // PERBAIKAN ENTERPRISE: Proteksi Branch Injection Pengirim
                if ($user && $user->role !== 'owner' && $request->from_branch_id != $user->branch_id) {
                    throw new \Exception("Akses ditolak: Anda hanya dapat memutasi stok keluar dari cabang Anda sendiri.");
                }

                $status = 'in_transit'; // Default untuk sistem kontrol pengiriman
                
                // Generator Nomor Dokumen Mutasi
                $dateCode = Carbon::parse($request->transfer_date)->format('Y/m');
                $count = DB::table('stock_transfers')
                            ->whereMonth('created_at', Carbon::parse($request->transfer_date)->month)
                            ->count() + 1;
                $transferNumber = "TRF/{$dateCode}/" . str_pad($count, 4, '0', STR_PAD_LEFT);

                // 1. Simpan Header Mutasi
                $transferId = DB::table('stock_transfers')->insertGetId([
                    'transfer_number' => $transferNumber,
                    'from_branch_id' => $request->from_branch_id,
                    'to_branch_id' => $request->to_branch_id,
                    'transfer_date' => $request->transfer_date,
                    'transfer_type' => 'transit',
                    'status' => $status,
                    'notes' => $request->notes,
                    'created_by' => $user->id ?? 1,
                    'created_at' => now(),
                    'updated_at' => now()
                ]);

                $totalTransferValue = 0; 
                $productNames = [];

                foreach ($request->items as $item) {
                    // Ambil info produk untuk pesan error & akuntansi
                    $product = DB::table('products')->where('id', $item['product_id'])->first();
                    
                    // PERBAIKAN: Pisahkan pengecekan null dan pengecekan tipe agar tidak error 500
                    if (!$product) {
                        throw new \Exception("Sistem Gagal: Produk dengan ID {$item['product_id']} tidak ditemukan di database.");
                    }

                    if (in_array($product->product_type, ['raw_material', 'consumable'])) {
                        throw new \Exception("Akses Ditolak: Produk '{$product->name}' adalah bahan baku / penolong dan tidak diizinkan untuk dimutasi antar cabang.");
                    }

                    $fullName = strtoupper($product->name) . ($product->variant_name ? " - " . strtoupper($product->variant_name) : "");
                    $productNames[] = $fullName;

                    $productName = strtoupper($product->name);

                    // 2. Cek Stok dengan Database Lock (Penting!)
                    $sourceStock = DB::table('product_stocks')
                        ->where('product_id', $item['product_id'])
                        ->where('branch_id', $request->from_branch_id)
                        ->lockForUpdate() 
                        ->first();

                    if (!$sourceStock || $sourceStock->quantity < $item['qty']) {
                        $currentQty = $sourceStock ? $sourceStock->quantity : 0;
                        throw new \Exception("Stok {$productName} tidak mencukupi! (Diminta: {$item['qty']}, Tersedia: {$currentQty})");
                    }

                    // 3. Kurangi stok gudang asal sekarang
                    DB::table('product_stocks')
                        ->where('id', $sourceStock->id)
                        ->decrement('quantity', $item['qty']);

                    // 4. Simpan Detail Item Mutasi
                    DB::table('stock_transfer_items')->insert([
                        'stock_transfer_id' => $transferId,
                        'product_id' => $item['product_id'],
                        'qty' => $item['qty']
                    ]);

                    // 5. Audit Trail - Stock Transaction Out
                    DB::table('stock_transactions')->insert([
                        'product_id' => $item['product_id'], 
                        'branch_id' => $request->from_branch_id, 
                        'type' => 'transfer_out', 
                        'input_quantity' => $item['qty'],
                        'input_unit' => $item['unit'] ?? 'PCS',
                        'actual_quantity' => -$item['qty'], 
                        'note' => "Mutasi Keluar ke {$transferNumber}", 
                        'user_id' => $user->id ?? 1,
                        'created_at' => now()
                    ]);

                    // Akumulasi nilai untuk Jurnal (HPP/Moving Average Cost)
                    $hppItem = (isset($product->average_cost) && $product->average_cost > 0) ? (float) $product->average_cost : (float) ($product->buy_price ?? 0);
                    $totalTransferValue += ($hppItem * $item['qty']);
                }

                // 6. Logika Akuntansi Enterprise (Journaling via AccountingService - STRICT GL)
                if ($totalTransferValue > 0) {
                    $invAccount = AccountingService::getAccountId('inventory_account');
                    $transitAccount = AccountingService::getAccountId('inventory_transit_account');

                    if (!$invAccount || !$transitAccount) {
                        throw new \Exception("Sistem Gagal: Master Akun Persediaan atau Persediaan Dalam Perjalanan (In Transit) belum dikonfigurasi.");
                    }

                    AccountingService::log([
                        'branch_id'   => $request->from_branch_id,
                        'entry_date'  => $request->transfer_date,
                        'description' => "Mutasi Keluar: " . implode(", ", array_unique($productNames)) . " - {$transferNumber}",
                        'reference'   => $transferNumber,
                        'source_type' => 'STOCK_TRANSFER',
                        'user_id'     => $user->id ?? 1,
                        'items'       => [
                            ['account_id' => $transitAccount, 'debit' => $totalTransferValue, 'credit' => 0],
                            ['account_id' => $invAccount, 'debit' => 0, 'credit' => $totalTransferValue]
                        ]
                    ]);
                }

                return response()->json([
                    'success' => true, 
                    'message' => 'Dokumen mutasi berhasil disimpan dan stok telah dikurangi.', 
                    'trf_number' => $transferNumber
                ]);
            });
            
        } catch (\Exception $e) {
            Log::error("Transfer Stock Error: " . $e->getMessage());
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }

    /**
     * Penerimaan Barang Mutasi (Selesaikan Transit)
     */
    public function receiveTransit(Request $request, $id)
    {
        try {
            return DB::transaction(function () use ($id) {
                $user = auth()->user();
                $transfer = DB::table('stock_transfers')->where('id', $id)->lockForUpdate()->first();

                if (!$transfer || $transfer->status !== 'in_transit') {
                    throw new \Exception("Status dokumen tidak valid untuk penerimaan.");
                }

                // PERBAIKAN ENTERPRISE: Proteksi Branch Injection Penerima
                if ($user && $user->role !== 'owner' && $transfer->to_branch_id != $user->branch_id) {
                    throw new \Exception("Akses ditolak: Anda hanya dapat menerima mutasi yang ditujukan ke cabang Anda.");
                }

                $items = DB::table('stock_transfer_items')->where('stock_transfer_id', $id)->get();
                $totalValue = 0;
                
                // 1. TAMBAHKAN BARIS INI: Penampung nama
                $productNames = [];

                foreach ($items as $item) {
                    // 2. TAMBAHKAN BARIS INI: Ambil nama produk dan varian
                    $product = DB::table('products')->where('id', $item->product_id)->first();
                    $fullName = $product ? (strtoupper($product->name) . ($product->variant_name ? " - " . strtoupper($product->variant_name) : "")) : "Barang ID " . $item->product_id;
                    $productNames[] = $fullName;

                    // 3. Update stok (Kode asli Anda)
                    DB::table('product_stocks')->updateOrInsert(
                        ['product_id' => $item->product_id, 'branch_id' => $transfer->to_branch_id],
                        ['quantity' => DB::raw("quantity + {$item->qty}"), 'updated_at' => now()]
                    );

                    // 4. Audit Trail (Kode asli Anda)
                    DB::table('stock_transactions')->insert([
                        'product_id' => $item->product_id, 
                        'branch_id' => $transfer->to_branch_id, 
                        'type' => 'transfer_in', 
                        'input_quantity' => $item->qty,
                        'input_unit' => 'PCS',
                        'actual_quantity' => $item->qty, 
                        'note' => "Penerimaan Mutasi dari {$transfer->transfer_number}", 
                        'user_id' => $user->id ?? 1,
                        'created_at' => now()
                    ]);

                    $hppItem = (isset($product->average_cost) && $product->average_cost > 0) ? (float) $product->average_cost : (float) ($product->buy_price ?? 0);
                    $totalValue += ($hppItem * $item->qty);
                }

                // Jurnal Penerimaan (STRICT GL)
                if ($totalValue > 0) {
                    $invAccount = AccountingService::getAccountId('inventory_account');
                    $transitAccount = AccountingService::getAccountId('inventory_transit_account');

                    if (!$invAccount || !$transitAccount) {
                        throw new \Exception("Sistem Gagal: Master Akun Persediaan atau Persediaan Dalam Perjalanan belum dikonfigurasi.");
                    }

                    AccountingService::log([
                        'branch_id'   => $transfer->to_branch_id,
                        'entry_date'  => date('Y-m-d'),
                        // 5. UPDATE DESKRIPSI DI SINI:
                        'description' => "Penerimaan Mutasi: " . implode(", ", array_unique($productNames)) . " - " . $transfer->transfer_number,
                        'reference'   => $transfer->transfer_number . "-RCV",
                        'source_type' => 'STOCK_TRANSFER_RECEIVE',
                        'user_id'     => $user->id ?? 1,
                        'items'       => [
                            ['account_id' => $invAccount, 'debit' => $totalValue, 'credit' => 0],
                            ['account_id' => $transitAccount, 'debit' => 0, 'credit' => $totalValue]
                        ]
                    ]);
                }

                DB::table('stock_transfers')->where('id', $id)->update(['status' => 'completed', 'updated_at' => now()]);

                return response()->json(['success' => true, 'message' => 'Stok diterima dan dijurnal.']);
            });
        } catch (\Exception $e) {
            Log::error("Receive Transit Error: " . $e->getMessage());
            return response()->json(['success' => false, 'message' => $e->getMessage()], 500);
        }
    }
}