<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\StockTransaction;
use App\Models\ProductStock;
use App\Models\Product;
use App\Models\Branch;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use App\Services\AccountingService;
use Carbon\Carbon;

class MigrationStockApiController extends Controller
{
    /**
     * HELPER UTAMA: Menghitung Qty Dasar (Base Unit) berdasarkan Satuan Input
     */
    private function calculateActualQty($product, $inputQty, $inputUnit)
    {
        if (strcasecmp($inputUnit, $product->unit) === 0) {
            return (float) $inputQty;
        }
        if ($product->buy_unit && strcasecmp($inputUnit, $product->buy_unit) === 0) {
            return (float) $inputQty * (float) ($product->conversion_factor ?: 1);
        }
        if ($product->unit_3_name && strcasecmp($inputUnit, $product->unit_3_name) === 0) {
            return (float) $inputQty * (float) ($product->conversion_3_qty ?: 1);
        }
        if ($product->unit_4_name && strcasecmp($inputUnit, $product->unit_4_name) === 0) {
            return (float) $inputQty * (float) ($product->conversion_4_qty ?: 1);
        }
        return false;
    }

    // --- 1. AMBIL DATA SALDO AWAL ---
    public function index(Request $request)
    {
        $user = $request->user();
        $query = StockTransaction::with(['product', 'branch', 'user'])
            ->where('type', 'initial');

        // PERBAIKAN ENTERPRISE: Isolasi Laporan per Cabang
        if ($user && $user->role !== 'owner') {
            $query->where('branch_id', $user->branch_id);
        }

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

        return response()->json(['success' => true, 'data' => $data]);
    }

    // --- 2. API UNTUK FORM INPUT MANUAL ---
    public function getBranches()
    {
        $branches = Branch::all();
        return response()->json(['success' => true, 'data' => $branches]);
    }

    public function getProducts(Request $request)
    {
        $branchId = $request->query('branch_id');
        if (!$branchId) {
            return response()->json(['success' => true, 'data' => []]);
        }

        // OPTIMASI: Menggunakan query yang lebih efisien untuk memfilter Produk Induk/Varian
        $products = Product::whereHas('branches', function ($query) use ($branchId) {
                $query->where('branches.id', $branchId);
            })
            ->where('is_active', true)
            // Memastikan produk yang tampil adalah produk yang bisa di-stok (Bukan parent yang punya varian)
            ->where(function ($q) {
                $q->whereNull('variant_group_id')
                  ->orWhere('variant_group_id', '')
                  ->orWhereRaw("NOT EXISTS (SELECT 1 FROM products as p2 WHERE p2.variant_group_id = CONCAT('VAR-', products.id))");
            })
            ->get();

        return response()->json(['success' => true, 'data' => $products]);
    }

    public function storeManual(Request $request)
    {
        $request->validate([
            'branch_id' => 'required',
            'product_id' => 'required',
            'input_quantity' => 'required|numeric|min:0.01',
            'input_unit' => 'required',
            'hpp_price' => 'required|numeric|min:0', // PERBAIKAN: Kewajiban input HPP
        ]);

        $user = $request->user();

        // PERBAIKAN ENTERPRISE: Cegah Input Silang Cabang
        if ($user && $user->role !== 'owner' && (int)$request->branch_id !== (int)$user->branch_id) {
            return response()->json(['success' => false, 'message' => 'Akses ditolak: Anda tidak memiliki wewenang untuk input stok ke cabang lain.'], 403);
        }

        $product = Product::find($request->product_id);
        if (!$product) return response()->json(['success' => false, 'message' => 'Produk tidak ditemukan.'], 404);

        $actualQty = $this->calculateActualQty($product, $request->input_quantity, $request->input_unit);
        if ($actualQty === false) {
            return response()->json(['success' => false, 'message' => "Satuan '{$request->input_unit}' tidak valid untuk produk ini."], 400);
        }

        DB::beginTransaction();
        try {
            // =====================================================================
            // PERBAIKAN HPP & AVERAGE COST (Kalkulasi sebelum stok fisik ditambah)
            // =====================================================================
            $hppInput = (float) $request->hpp_price;
            $totalValue = $actualQty * $hppInput; 

            $currentStock = DB::table('product_stocks')->where('product_id', $product->id)->sum('quantity');
            $currentAvg = (float) ($product->average_cost ?? 0);

            if ($currentStock <= 0) {
                // Jika stok habis/kosong, paksa average cost dan buy price mengikuti HPP Migrasi ini
                DB::table('products')->where('id', $product->id)->update([
                    'average_cost' => $hppInput,
                    'buy_price' => $hppInput 
                ]);
            } else {
                // Jika sudah ada stok, lakukan metode Moving Average
                $totalValueOld = $currentStock * $currentAvg;
                $newAvg = ($totalValueOld + $totalValue) / ($currentStock + $actualQty);
                DB::table('products')->where('id', $product->id)->update([
                    'average_cost' => $newAvg
                ]);
            }

            // =====================================================================
            // Bypass Eloquent Observer untuk Mencegah Double Stok
            // =====================================================================
            $transactionId = DB::table('stock_transactions')->insertGetId([
                'branch_id' => $request->branch_id,
                'product_id' => $request->product_id,
                'type' => 'initial',
                'input_quantity' => $request->input_quantity,
                'input_unit' => $request->input_unit,
                'actual_quantity' => $actualQty,
                'note' => $request->note ?: 'Input Saldo Awal Manual',
                'user_id' => $user->id,
                'created_at' => Carbon::now(),
                'updated_at' => Carbon::now(),
            ]);

            // Tambah Stok Fisik
            $stock = ProductStock::firstOrCreate(
                ['product_id' => $request->product_id, 'branch_id' => $request->branch_id],
                ['quantity' => 0]
            );
            $stock->quantity += $actualQty;
            $stock->save();

            // 3. JURNAL AKUNTANSI (Menggunakan totalValue dari HPP Input)
            $inventoryAcc = AccountingService::getAccountId('inventory_account'); 
            $equityAcc = AccountingService::getAccountId('default_migration_equity_account'); 

            if (!$inventoryAcc || !$equityAcc) {
                throw new \Exception("Akun Persediaan Barang atau Akun Modal untuk migrasi belum tersedia di Master Akun Global.");
            }

            if ($totalValue > 0) {
                AccountingService::log([
                    'branch_id'   => $request->branch_id,
                    'entry_date'  => now()->toDateString(),
                    'description' => "Saldo Awal Stok: " . $product->name . ($product->variant_name ? " - " . $product->variant_name : ""),
                    'reference'   => "MIG-STK-" . $transactionId, 
                    'source_type' => 'migration_stock',
                    'user_id'     => $user->id,
                    'items' => [
                        ['account_id' => $inventoryAcc, 'debit' => $totalValue, 'credit' => 0],
                        ['account_id' => $equityAcc, 'debit' => 0, 'credit' => $totalValue],
                    ]
                ]);
            }

            DB::commit();
            return response()->json(['success' => true, 'message' => 'Saldo awal manual berhasil ditambahkan dan Valuasi HPP terkunci!']);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => 'Gagal menyimpan: ' . $e->getMessage()], 500);
        }
    }

    // --- 3. API UNTUK UPDATE DAN DELETE (DENGAN SINKRONISASI JURNAL) ---
    public function update(Request $request, $id)
    {
        $request->validate([
            'input_quantity' => 'required|numeric|min:0.01',
            'input_unit' => 'required',
            'hpp_price' => 'required|numeric|min:0', // PERBAIKAN
        ]);

        $user = $request->user();

        DB::beginTransaction();
        try {
            $transaction = DB::table('stock_transactions')->where('id', $id)->first();
            if (!$transaction) throw new \Exception("Data Mutasi tidak ditemukan.");

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

            $product = Product::findOrFail($transaction->product_id);

            $newActualQty = $this->calculateActualQty($product, $request->input_quantity, $request->input_unit);
            if ($newActualQty === false) {
                throw new \Exception("Satuan '{$request->input_unit}' tidak valid.");
            }

            $oldActualQty = $transaction->actual_quantity;

            // 1. Update Tabel Transaksi
            DB::table('stock_transactions')->where('id', $id)->update([
                'input_quantity' => $request->input_quantity,
                'input_unit' => $request->input_unit,
                'actual_quantity' => $newActualQty,
                'note' => $request->note,
                'updated_at' => Carbon::now(),
            ]);

            // 2. Sesuaikan Stok Fisik
            $stock = ProductStock::where('product_id', $transaction->product_id)
                                 ->where('branch_id', $transaction->branch_id)
                                 ->first();
            if ($stock) {
                $stock->quantity = $stock->quantity - $oldActualQty + $newActualQty;
                $stock->save();
            }

            // 3. UPDATE JURNAL AKUNTANSI DAN PAKSA KOREKSI HPP
            $hpp = (float) $request->hpp_price;
            $newTotalValue = $newActualQty * $hpp;

            // Memaksa HPP rata-rata produk menjadi nilai edit terbaru agar konsisten
            DB::table('products')->where('id', $product->id)->update(['average_cost' => $hpp]);

            $journal = \App\Models\JournalEntry::where('reference', "MIG-STK-" . $transaction->id)
                ->where('source_type', 'migration_stock')
                ->first();

            if ($journal && $newTotalValue > 0) {
                $inventoryAcc = AccountingService::getAccountId('inventory_account'); 
                $equityAcc = AccountingService::getAccountId('default_migration_equity_account'); 

                if (!$inventoryAcc || !$equityAcc) {
                    throw new \Exception("Konfigurasi Master Akun Global hilang.");
                }

                \App\Models\JournalItem::where('journal_entry_id', $journal->id)
                    ->where('account_id', $inventoryAcc)
                    ->update(['debit' => $newTotalValue, 'credit' => 0]);
                    
                \App\Models\JournalItem::where('journal_entry_id', $journal->id)
                    ->where('account_id', $equityAcc)
                    ->update(['debit' => 0, 'credit' => $newTotalValue]);
            }

            DB::commit();
            return response()->json(['success' => true, 'message' => 'Saldo awal dan nilai Jurnal berhasil diperbarui!']);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => 'Gagal update: ' . $e->getMessage()], 500);
        }
    }

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

        DB::beginTransaction();
        try {
            $transaction = DB::table('stock_transactions')->where('id', $id)->first();
            if (!$transaction) throw new \Exception("Data tidak ditemukan.");

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

            // 1. Tarik Kembali (Revert) Stok Fisik
            $stock = ProductStock::where('product_id', $transaction->product_id)
                                 ->where('branch_id', $transaction->branch_id)
                                 ->first();
            if ($stock) {
                $stock->quantity -= $transaction->actual_quantity;
                $stock->save();
            }

            // 2. HAPUS JURNAL TERKAIT
            $journal = \App\Models\JournalEntry::where('reference', "MIG-STK-" . $transaction->id)
                ->where('source_type', 'migration_stock')
                ->first();
                
            if ($journal) {
                \App\Models\JournalItem::where('journal_entry_id', $journal->id)->delete();
                $journal->delete();
            }

            // 3. Hapus Catatan
            DB::table('stock_transactions')->where('id', $id)->delete();

            DB::commit();
            return response()->json(['success' => true, 'message' => 'Data saldo awal dan Jurnal terkait berhasil dihapus!']);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => 'Gagal hapus: ' . $e->getMessage()], 500);
        }
    }

    // --- 4. API UNTUK UPLOAD MASSAL CSV ---
    public function previewCsv(Request $request)
    {
        $request->validate(['file' => 'required|mimes:csv,txt']);
        $user = $request->user();

        $file = $request->file('file');
        $handle = fopen($file->getPathname(), "r");
        
        $header = fgetcsv($handle, 1000, ","); 
        $previewData = [];
        $row = 2;

        while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
            $sku = trim($data[0] ?? '');
            $kodeCabang = trim($data[1] ?? '');
            $qty = trim($data[2] ?? 0);
            $satuan = trim($data[3] ?? '');
            $keterangan = trim($data[4] ?? '');
            $hpp = trim($data[5] ?? 0); // PERBAIKAN: Mengambil data HPP dari CSV

            $isValid = true;
            $errors = [];
            $actualQty = 0;

            $product = Product::where('sku', $sku)->first();
            if (!$product) { $isValid = false; $errors[] = "SKU '$sku' tidak ditemukan."; }

            $branch = Branch::where('code', $kodeCabang)->first();
            if (!$branch) { 
                $isValid = false; 
                $errors[] = "Cabang '$kodeCabang' tidak valid."; 
            } else {
                if ($user && $user->role !== 'owner' && $branch->id !== $user->branch_id) {
                    $isValid = false; 
                    $errors[] = "Akses ditolak untuk Cabang '$kodeCabang'.";
                }
            }

            if (!is_numeric($qty) || $qty <= 0) { $isValid = false; $errors[] = "Qty harus angka > 0."; }
            if (!is_numeric($hpp) || $hpp < 0) { $isValid = false; $errors[] = "HPP harus angka >= 0."; }

            if ($product && $isValid) {
                $satuanToCheck = $satuan ?: $product->unit; 
                $calculatedQty = $this->calculateActualQty($product, $qty, $satuanToCheck);
                
                if ($calculatedQty === false) {
                    $isValid = false;
                    $errors[] = "Satuan '$satuanToCheck' tidak dikenali sistem.";
                } else {
                    $actualQty = $calculatedQty;
                    $satuan = $satuanToCheck; 
                }
            }

            $previewData[] = [
                'row' => $row,
                'sku' => $sku,
                'product_name' => $product ? $product->name . ($product->variant_name ? " ({$product->variant_name})" : '') : '-',
                'branch_code' => $kodeCabang,
                'branch_name' => $branch ? $branch->name : '-',
                'qty' => $qty,
                'satuan' => $satuan,
                'actual_qty' => $actualQty,
                'hpp' => $hpp, // PERBAIKAN
                'keterangan' => $keterangan,
                'is_valid' => $isValid,
                'errors' => implode(", ", $errors),
                'product_id' => $product->id ?? null,
                'branch_id' => $branch->id ?? null,
            ];
            $row++;
        }
        fclose($handle);

        return response()->json(['success' => true, 'data' => $previewData]);
    }

    public function importData(Request $request)
    {
        $items = $request->items;
        $user = $request->user();
        $successCount = 0;

        DB::beginTransaction();
        try {
            $inventoryAcc = AccountingService::getAccountId('inventory_account'); 
            $equityAcc = AccountingService::getAccountId('default_migration_equity_account'); 

            if (!$inventoryAcc || !$equityAcc) {
                throw new \Exception("Akun Persediaan Barang atau Akun Modal untuk migrasi belum tersedia di Master Akun Global.");
            }

            foreach ($items as $item) {
                if (!$item['is_valid']) continue;

                if ($user && $user->role !== 'owner' && (int)$item['branch_id'] !== (int)$user->branch_id) {
                    continue; 
                }

                // =====================================================================
                // PERBAIKAN HPP & AVERAGE COST PADA IMPORT CSV
                // =====================================================================
                $product = Product::find($item['product_id']);
                $hppInput = (float) $item['hpp'];
                $totalValue = $item['actual_qty'] * $hppInput;

                $currentStock = DB::table('product_stocks')->where('product_id', $product->id)->sum('quantity');
                $currentAvg = (float) ($product->average_cost ?? 0);

                if ($currentStock <= 0) {
                    DB::table('products')->where('id', $product->id)->update([
                        'average_cost' => $hppInput,
                        'buy_price' => $hppInput 
                    ]);
                } else {
                    $totalValueOld = $currentStock * $currentAvg;
                    $newAvg = ($totalValueOld + $totalValue) / ($currentStock + $item['actual_qty']);
                    DB::table('products')->where('id', $product->id)->update([
                        'average_cost' => $newAvg
                    ]);
                }

                $transactionId = DB::table('stock_transactions')->insertGetId([
                    'branch_id' => $item['branch_id'],
                    'product_id' => $item['product_id'],
                    'type' => 'initial',
                    'input_quantity' => $item['qty'],
                    'input_unit' => $item['satuan'],
                    'actual_quantity' => $item['actual_qty'],
                    'note' => $item['keterangan'] ?: 'Import Saldo Awal',
                    'user_id' => $user->id,
                    'created_at' => Carbon::now(),
                    'updated_at' => Carbon::now(),
                ]);

                $stock = ProductStock::firstOrCreate(
                    ['product_id' => $item['product_id'], 'branch_id' => $item['branch_id']],
                    ['quantity' => 0]
                );
                $stock->quantity += $item['actual_qty']; 
                $stock->save();

                // ----------------------------------------------------
                // JURNAL AKUNTANSI VIA ACCOUNTING SERVICE
                // ----------------------------------------------------
                if ($totalValue > 0) {
                    AccountingService::log([
                        'branch_id'   => $item['branch_id'],
                        'entry_date'  => now()->toDateString(),
                        'description' => "Saldo Awal Stok (Import): " . $product->name . ($product->variant_name ? " - " . $product->variant_name : ""),
                        'reference'   => "MIG-STK-" . $transactionId,
                        'source_type' => 'migration_stock',
                        'user_id'     => $user->id,
                        'items' => [
                            ['account_id' => $inventoryAcc, 'debit' => $totalValue, 'credit' => 0],
                            ['account_id' => $equityAcc, 'debit' => 0, 'credit' => $totalValue],
                        ]
                    ]);
                }
                // ----------------------------------------------------

                $successCount++;
            }
            DB::commit();
            return response()->json(['success' => true, 'message' => "$successCount data berhasil diimport dan dijurnal secara akurat!"]);
        } catch (\Exception $e) {
            DB::rollBack();
            return response()->json(['success' => false, 'message' => 'Gagal import: ' . $e->getMessage()], 500);
        }
    }
}