<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Item;
use App\Models\Store;
use App\Models\Inventory;
use App\Models\PurchaseHistory;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class TransactionController extends Controller
{
    public function sell(Request $request)
    {
        $validated = $request->validate([
            'store_id' => 'required|exists:stores,id',
            'item_id'  => 'required|exists:items,id',
            'qty'      => 'required|numeric|min:1',
        ]);

        DB::beginTransaction();
        try {
            $this->checkFeatureAccess($request, $validated['store_id'], 'pos_cashier', 'can_add');

            $store = Store::findOrFail($validated['store_id']);
            $item = Item::with('ingredients')->findOrFail($validated['item_id']);

            $this->processDeduction($item, $validated['qty'], $store);

            $totalRevenue = $item->price * $validated['qty'];
            
            \App\Models\TransactionLedger::create([
                'store_id'         => $store->id,
                'transaction_date' => now(),
                'type'             => 'income',
                'category'         => 'sales_revenue',
                'amount'           => $totalRevenue,
                'description'      => "Penjualan {$validated['qty']}x {$item->name}"
            ]);
            
            $hppPerUnit = $this->calculateHpp($item);
            $totalHppExpense = $hppPerUnit * $validated['qty'];

            if ($totalHppExpense > 0) {
                \App\Models\TransactionLedger::create([
                    'store_id'         => $store->id,
                    'transaction_date' => now(),
                    'type'             => 'expense', 
                    'category'         => 'cogs_expense', 
                    'amount'           => $totalHppExpense,
                    'description'      => "HPP (Modal Bahan) untuk {$validated['qty']}x {$item->name}"
                ]);
            }
            
            DB::commit();

            return response()->json([
                'status'  => 'success',
                'message' => "Transaksi sukses. Uang Rp " . number_format($totalRevenue) . " tercatat di buku besar."
            ], 200);

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

    public function produce(Request $request)
    {
        $validated = $request->validate([
            'store_id' => 'required|exists:stores,id',
            'item_id'  => 'required|exists:items,id',
            'qty'      => 'required|numeric|min:1',
        ]);

        DB::beginTransaction();
        try {
            $this->checkFeatureAccess($request, $validated['store_id'], 'production', 'can_add');

            $store = Store::findOrFail($validated['store_id']);
            $item = Item::with('ingredients')->findOrFail($validated['item_id']);

            if ($item->ingredients->isEmpty()) {
                throw new \Exception("Item {$item->name} tidak memiliki resep untuk diproduksi.");
            }

            foreach ($item->ingredients as $ingredient) {
                $totalNeeded = $validated['qty'] * $ingredient->pivot->qty_needed;
                
                $inv = Inventory::firstOrCreate(
                    ['store_id' => $store->id, 'item_id' => $ingredient->id],
                    ['current_stock' => 0]
                );

                if ($inv->current_stock < $totalNeeded) {
                     throw new \Exception("Produksi gagal. Stok {$ingredient->name} tidak cukup.");
                }

                $inv->current_stock -= $totalNeeded;
                $inv->save();
            }

            $parentInv = Inventory::firstOrCreate(
                ['store_id' => $store->id, 'item_id' => $item->id],
                ['current_stock' => 0]
            );
            $parentInv->current_stock += $validated['qty'];
            $parentInv->save();

            DB::commit();

            return response()->json([
                'status'  => 'success',
                'message' => "Produksi {$item->name} berhasil."
            ], 200);

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

    public function purchase(Request $request)
    {
        $validated = $request->validate([
            'store_id'      => 'required|exists:stores,id',
            'item_id'       => 'required|exists:items,id',
            'qty'           => 'required|numeric|min:0.1',
            'total_cost'    => 'required|numeric|min:0',
            'unit_cost'     => 'required|numeric|min:0',
            // KUNCI MUTLAK: Validasi ID supplier, bukan lagi teks nama
            'supplier_id'   => 'nullable|exists:suppliers,id', 
            'purchased_at'  => 'required|date',
        ]);

        DB::beginTransaction();
        try {
            $this->checkFeatureAccess($request, $validated['store_id'], 'inbound_purchase', 'can_add');

            PurchaseHistory::create($validated);

            $inventory = Inventory::firstOrCreate(
                ['store_id' => $validated['store_id'], 'item_id' => $validated['item_id']],
                ['current_stock' => 0]
            );
            
            $inventory->current_stock += $validated['qty'];
            $inventory->save();

            DB::commit();

            return response()->json([
                'status'  => 'success',
                'message' => "Barang masuk berhasil dicatat."
            ], 200);

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

    private function processDeduction($item, $qtyNeeded, $store)
    {
        if ($item->type === 'produk') {
            if ($item->ingredients->isEmpty()) {
                throw new \Exception("Produk {$item->name} tidak memiliki resep.");
            }
            foreach ($item->ingredients as $ingredient) {
                $totalIngredientNeeded = $qtyNeeded * $ingredient->pivot->qty_needed;
                $this->processDeduction($ingredient, $totalIngredientNeeded, $store);
            }
            return; 
        }

        $inventory = Inventory::firstOrCreate(
            ['store_id' => $store->id, 'item_id' => $item->id],
            ['current_stock' => 0]
        );

        if ($inventory->current_stock >= $qtyNeeded) {
            $inventory->current_stock -= $qtyNeeded;
            $inventory->save();
        } else {
            if (!$store->auto_replenish) {
                throw new \Exception("Stok {$item->name} tidak mencukupi.");
            } else {
                $inventory->current_stock -= $qtyNeeded;
                $inventory->save();
            }
        }
    }

    private function checkFeatureAccess($request, $storeId, $feature, $action)
    {
        // PERBAIKAN MUTLAK
        $user = $request->user();
        if (!$user) {
            throw new \Exception('Sesi tidak valid. Harap login kembali.');
        }

        $storeUser = DB::table('store_user')
            ->where('store_id', $storeId)
            ->where('user_id', $user->id)
            ->first();

        if (!$storeUser) {
            throw new \Exception('Anda tidak terdaftar di toko ini.');
        }

        if ($storeUser->role === 'owner') {
            return true;
        }

        $permission = DB::table('store_role_permissions')
            ->where('store_id', $storeId)
            ->where('role', $storeUser->role)
            ->where('feature', $feature)
            ->first();

        if (!$permission || !$permission->{$action}) {
            throw new \Exception("Akses ditolak. Jabatan {$storeUser->role} tidak punya izin {$action} pada {$feature}.");
        }

        return true;
    }

    private function calculateHpp($item)
    {
        if ($item->type === 'produk' || $item->type === 'sub_bahan') {
            $totalHpp = 0;
            foreach ($item->ingredients as $ingredient) {
                $totalHpp += ($this->calculateHpp($ingredient) * $ingredient->pivot->qty_needed);
            }
            return $totalHpp;
        }

        $lastPurchase = \App\Models\PurchaseHistory::where('item_id', $item->id)
                            ->latest('purchased_at')
                            ->first();

        return $lastPurchase ? $lastPurchase->unit_cost : 0;
    }
    /**
     * FITUR: TAMBAH BIAYA OPERASIONAL
     */
    public function addExpense(Request $request)
    {
        $validated = $request->validate([
            'store_id'    => 'required|exists:stores,id',
            'description' => 'required|string|max:255',
            'qty'         => 'required|numeric|min:1',
            'amount'      => 'required|numeric|min:0',
            'category'    => 'required|string|max:100',
            'notes'       => 'nullable|string',
        ]);

        DB::beginTransaction();
        try {
            // Gembok Wewenang: Hanya yang punya izin "can_add" di fitur "expense_management"
            $this->checkFeatureAccess($request, $validated['store_id'], 'expense_management', 'can_add');

            $totalAmount = $validated['qty'] * $validated['amount'];
            $fullDescription = $validated['description'];
            if (!empty($validated['notes'])) {
                $fullDescription .= ' - ' . $validated['notes'];
            }

            \App\Models\TransactionLedger::create([
                'store_id'         => $validated['store_id'],
                'transaction_date' => now(),
                'type'             => 'expense',
                'category'         => $validated['category'], // Menyimpan kategori dinamis
                'amount'           => $totalAmount,
                'description'      => $fullDescription
            ]);

            DB::commit();

            return response()->json([
                'status'  => 'success',
                'message' => 'Biaya berhasil dicatat ke buku besar.'
            ], 200);

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

    /**
     * FITUR: AMBIL DAFTAR KATEGORI DINAMIS
     */
    public function getExpenseCategories(Request $request)
    {
        try {
            $storeId = $request->query('store_id');
            // Tarik kategori unik dari buku besar pengeluaran
            $categories = \App\Models\TransactionLedger::where('store_id', $storeId)
                            ->where('type', 'expense')
                            ->select('category')
                            ->distinct()
                            ->pluck('category');

            return response()->json(['status' => 'success', 'data' => $categories], 200);
        } catch (\Exception $e) {
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }
    /**
     * FITUR: TARIK DATA BUKU BESAR DENGAN PAGINATION
     */
    public function getLedger(Request $request)
    {
        $validated = $request->validate([
            'store_id' => 'required|exists:stores,id',
        ]);

        try {
            // Kita bisa menggunakan izin view pnl_report atau izin ledger khusus
            $this->checkFeatureAccess($request, $validated['store_id'], 'pnl_report', 'can_view');

            // Tarik data diurutkan dari yang paling baru
            $ledgers = \App\Models\TransactionLedger::where('store_id', $validated['store_id'])
                            ->orderBy('transaction_date', 'desc')
                            ->orderBy('id', 'desc')
                            ->paginate(10);

            return response()->json([
                'status' => 'success',
                'data' => $ledgers
            ], 200);

        } catch (\Exception $e) {
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }

    /**
     * FITUR: UPDATE JURNAL BUKU BESAR
     */
    public function updateLedger(Request $request, $id)
    {
        $validated = $request->validate([
            'description' => 'required|string|max:255',
            'amount'      => 'required|numeric|min:0',
            'category'    => 'required|string|max:100',
        ]);

        try {
            $ledger = \App\Models\TransactionLedger::findOrFail($id);
            // Tambahkan proteksi checkFeatureAccess di sini nanti jika perlu
            
            $ledger->update([
                'description' => $validated['description'],
                'amount'      => $validated['amount'],
                'category'    => $validated['category']
            ]);

            return response()->json(['status' => 'success', 'message' => 'Jurnal berhasil diperbarui.'], 200);
        } catch (\Exception $e) {
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }

    /**
     * FITUR: DELETE JURNAL BUKU BESAR
     */
    public function deleteLedger($id)
    {
        try {
            $ledger = \App\Models\TransactionLedger::findOrFail($id);
            $ledger->delete();

            return response()->json(['status' => 'success', 'message' => 'Jurnal berhasil dihapus.'], 200);
        } catch (\Exception $e) {
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }

    /**
     * FITUR: TAMBAH DATA MASTER BARU (Bahan Baku, Sub Bahan, Produk)
     */
    public function addMasterItem(Request $request)
    {
        $validated = $request->validate([
            'store_id' => 'required|exists:stores,id',
            'type'     => 'required|in:bahan_baku,sub_bahan,produk',
            'name'     => 'required|string|max:255',
            'uom'      => 'required|string|max:50',
            'price'    => 'nullable|numeric|min:0',
        ]);

        $recipes = $request->input('recipes', []);

        try {
            \Illuminate\Support\Facades\DB::beginTransaction();

            // Insert item dan tangkap ID barunya
            $itemId = \Illuminate\Support\Facades\DB::table('items')->insertGetId([
                'store_id' => $validated['store_id'],
                'type'     => $validated['type'],
                'name'     => $validated['name'],
                'uom'      => $validated['uom'],
                'price'    => $validated['price'] ?: 0,
                'created_at' => now(),
                'updated_at' => now(),
            ]);

            // Jika ada resepnya, masukkan ke tabel item_recipes
            if (!empty($recipes)) {
                foreach ($recipes as $recipe) {
                    \Illuminate\Support\Facades\DB::table('item_recipes')->insert([
                        'parent_item_id' => $itemId,
                        'child_item_id'  => $recipe['material_id'],
                        'qty_needed'     => $recipe['qty'],
                        'created_at'     => now(),
                        'updated_at'     => now(),
                    ]);
                }
            }

            \Illuminate\Support\Facades\DB::commit();
            return response()->json(['status' => 'success', 'message' => 'Data master berhasil ditambahkan!'], 200);
        } catch (\Exception $e) {
            \Illuminate\Support\Facades\DB::rollBack();
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }
    
    /**
     * FITUR: AMBIL DATA MASTER & RESEP (GET)
     */
    public function getMasterItems(Request $request)
    {
        $storeId = $request->query('store_id');
        $type = $request->query('type');

        try {
            $items = \Illuminate\Support\Facades\DB::table('items')
                        ->where('store_id', $storeId)
                        ->where('type', $type)
                        ->orderBy('name', 'asc')
                        ->get();

            $formattedItems = $items->map(function($item) {
                $recipes = [];
                try {
                    if ($item->type !== 'bahan_baku') {
                        // KUNCI MUTLAK: Disesuaikan dengan tabel item_recipes milikmu
                        $recipes = \Illuminate\Support\Facades\DB::table('item_recipes')
                                ->join('items as material', 'item_recipes.child_item_id', '=', 'material.id')
                                ->where('item_recipes.parent_item_id', $item->id)
                                ->select(
                                    'item_recipes.child_item_id as material_id', // Alias agar frontend tidak error
                                    'material.name as material_name', 
                                    'item_recipes.qty_needed as qty', // Alias agar frontend tidak error
                                    'material.uom', 
                                    'material.price as hpp_per_uom'
                                )->get();
                    }
                } catch (\Exception $e) { }

                return [
                    'id'      => $item->id,
                    'name'    => $item->name,
                    'uom'     => $item->uom,
                    'price'   => $item->price,
                    'type'    => $item->type,
                    'recipes' => $recipes
                ];
            });

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

    /**
     * FITUR: DELETE MASTER ITEM (Bahan Baku / Produk / Sub Bahan)
     */
    public function deleteMasterItem($id)
    {
        try {
            // Hapus resep di item_recipes dulu
            \Illuminate\Support\Facades\DB::table('item_recipes')->where('parent_item_id', $id)->delete();
            // Baru hapus itemnya
            \Illuminate\Support\Facades\DB::table('items')->where('id', $id)->delete();

            return response()->json(['status' => 'success', 'message' => 'Data Master berhasil dihapus.'], 200);
        } catch (\Exception $e) {
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }

    public function getItemRecipes($id)
    {
        try {
            $recipes = \Illuminate\Support\Facades\DB::table('item_recipes')
                ->join('items as material', 'item_recipes.child_item_id', '=', 'material.id')
                ->where('item_recipes.parent_item_id', $id)
                ->select(
                    'item_recipes.child_item_id as material_id', 
                    'item_recipes.qty_needed as qty', 
                    'material.name as material_name', 
                    'material.uom', 
                    'material.price as hpp_per_uom'
                )
                ->get();

            return response()->json(['status' => 'success', 'data' => $recipes], 200);
        } catch (\Exception $e) {
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }

    public function updateItemRecipes(Request $request, $id)
    {
        $recipes = $request->input('recipes', []);

        try {
            \Illuminate\Support\Facades\DB::beginTransaction();

            // 1. Hapus resep lama
            \Illuminate\Support\Facades\DB::table('item_recipes')->where('parent_item_id', $id)->delete();

            // 2. Masukkan resep baru
            foreach ($recipes as $recipe) {
                \Illuminate\Support\Facades\DB::table('item_recipes')->insert([
                    'parent_item_id' => $id,
                    'child_item_id'  => $recipe['material_id'],
                    'qty_needed'     => $recipe['qty'],
                    'created_at'     => now(),
                    'updated_at'     => now(),
                ]);
            }

            \Illuminate\Support\Facades\DB::commit();
            return response()->json(['status' => 'success', 'message' => 'Resep berhasil diperbarui.'], 200);
        } catch (\Exception $e) {
            \Illuminate\Support\Facades\DB::rollBack();
            return response()->json(['status' => 'error', 'message' => $e->getMessage()], 400);
        }
    }

}