<?php

namespace App\Http\Controllers;

use App\Models\Sale;
use App\Models\Stock;
use App\Models\JournalEntry;
use App\Models\JournalDetail;
use App\Models\Account;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;

class SaleController extends Controller
{
    public function index(Request $request)
    {
        $user = Auth::user();
        $branches = \App\Models\Branch::all();
        
        $query = Sale::with('product')->orderBy('date', 'desc');

        if ($request->filled('year')) {
            $query->whereYear('date', $request->year);
        }
        if ($request->filled('month')) {
            $query->whereMonth('date', $request->month);
        }
        if ($request->filled('day')) {
            $query->whereDay('date', $request->day);
        }

        if ($request->filled('search')) {
            $query->where('item', 'like', '%' . $request->search . '%');
        }

        // Apply "today" filter by default only when the page is first loaded
        // (i.e. there are no query parameters). If the user submitted the filter
        // form with "Semua Tahun" (empty values), we treat that as an explicit
        // request and do not force today's data.
        if (count($request->query()) === 0) {
            $query->whereDate('date', \Carbon\Carbon::today());
        }

        if ($user->role === 'admin') {
            $products = \App\Models\Product::all();
            $sales = $query->get();
            // We no longer need salesByBranch as we use a single consolidated view
            return view('laporan_penjualan', compact('sales', 'products', 'branches'));
        } else {
            $products = \App\Models\Product::all();
            $sales = $query->where('branch', $user->branch)->get();
            return view('laporan_penjualan', compact('sales', 'products', 'branches'));
        }
    }

    public function create()
    {
        $user = Auth::user();

        if ($user->role === 'admin') {
            return redirect('/laporan/penjualan')->with('error', 'Fitur tambah penjualan hanya tersedia untuk karyawan.');
        }

        $branches = \App\Models\Branch::all();
        $branch = $user->branch ?? 'Cabang 1';
        $products = \App\Models\Product::where('branch', $branch)->get();

        return view('transaksi.penjualan', compact('branches', 'products'));
    }

    public function exportPdf(Request $request)
    {
        $user = Auth::user();
        if ($user->role !== 'admin') {
            abort(403);
        }

        $query = Sale::with('product')->orderBy('date', 'desc');

        if ($request->filled('year')) {
            $query->whereYear('date', $request->year);
        }
        if ($request->filled('month')) {
            $query->whereMonth('date', $request->month);
        }
        if ($request->filled('day')) {
            $query->whereDay('date', $request->day);
        }

        if ($request->filled('search')) {
            $query->where('item', 'like', '%' . $request->search . '%');
        }

        // Apply "today" filter by default only when the page is first loaded
        // (i.e. there are no query parameters). If the admin submits the filter
        // form with empty values intentionally, return the full dataset.
        if (count($request->query()) === 0) {
            $query->whereDate('date', \Carbon\Carbon::today());
        }

        $sales = $query->get();
        $branches = \App\Models\Branch::all();
        
        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('reports.sale_pdf', compact('sales', 'branches'));
        return $pdf->download('laporan_penjualan.pdf');
    }

    public function store(Request $request)
    {
        $request->validate([
            'date' => 'required|date',
            'product_id' => 'required|exists:products,id',
            'quantity' => 'required|integer|min:1',
            'total_price' => 'required|numeric|min:0',
        ]);

        try {
            \Illuminate\Support\Facades\DB::transaction(function () use ($request) {
                $product = \App\Models\Product::findOrFail($request->product_id);

                $branch = Auth::user()->branch ?? 'Cabang 1';
                if (Auth::user()->role === 'admin' && $request->has('branch')) {
                    $branch = $request->branch;
                }

                // Bersihkan format angka (hapus titik pemisah ribuan jika ada)
                $cleanPrice = str_replace('.', '', $request->total_price);

                // First, adjust stocks: either raw materials (if product has recipes)
                // or product stock per branch
                $product = \App\Models\Product::with('recipes.rawMaterial')->findOrFail($request->product_id);

                if ($product->recipes->count() > 0) {
                    // Check and deduct raw materials
                    foreach ($product->recipes as $recipe) {
                        $rm = $recipe->rawMaterial;
                        if (!$rm) continue;
                        $needed = $recipe->quantity_needed * $request->quantity;
                        if ($rm->stock_quantity < $needed) {
                            throw new \Exception('Bahan baku tidak cukup untuk membuat ' . $request->quantity . ' porsi.');
                        }
                    }

                    foreach ($product->recipes as $recipe) {
                        $rm = $recipe->rawMaterial;
                        if ($rm) {
                            $needed = $recipe->quantity_needed * $request->quantity;
                            $rm->stock_quantity -= $needed;
                            if ($rm->stock_quantity < 0) $rm->stock_quantity = 0;
                            $rm->save();
                        }
                    }

                    // Recalculate finished product stock once after all raw materials are updated
                    $this->recalculateProductsFromRawMaterials($product->id, $branch);
                } else {
                    // Deduct from regular stock
                    $stock = \App\Models\Stock::where('product_id', $request->product_id)->where('branch', $branch)->first();
                    if (!$stock) {
                        throw new \Exception('Stok untuk produk ini tidak ditemukan pada cabang Anda.');
                    }

                    if ($stock->quantity < $request->quantity) {
                        throw new \Exception('Stok tidak cukup. Tersedia: ' . $stock->quantity);
                    }

                    $stock->quantity = $stock->quantity - $request->quantity;
                    if ($stock->quantity < 0) $stock->quantity = 0;
                    $stock->save();
                }

                // Now create sale record
                $sale = Sale::create([
                    'date' => $request->date,
                    'branch' => $branch,
                    'product_id' => $request->product_id,
                    'item' => $product->name,
                    'quantity' => $request->quantity,
                    'total_price' => (int) $cleanPrice,
                ]);

                // Create Journal Entry
                $kasAccount = $this->ensureAccount('101', 'Kas', 'Asset');
                $penjualanAccount = $this->ensureAccount('401', 'Penjualan', 'Revenue');
                $hppAccount = $this->ensureAccount('501', 'Harga Pokok Penjualan', 'Expense');
                $persediaanAccount = $this->ensureAccount('102', 'Persediaan Barang Dagang', 'Asset');

                $journal = JournalEntry::create([
                    'date' => $sale->date,
                    'description' => 'Penjualan ' . $sale->item,
                    'reference_type' => 'Sale',
                    'reference_id' => $sale->id,
                    'branch' => $branch,
                ]);

                // Debit Kas, Kredit Penjualan
                JournalDetail::create(['journal_entry_id' => $journal->id, 'account_id' => $kasAccount->id, 'debit' => $sale->total_price, 'credit' => 0]);
                JournalDetail::create(['journal_entry_id' => $journal->id, 'account_id' => $penjualanAccount->id, 'debit' => 0, 'credit' => $sale->total_price]);

                // Debit HPP, Kredit Persediaan
                $hppTotal = $sale->quantity * $product->purchase_price;
                JournalDetail::create(['journal_entry_id' => $journal->id, 'account_id' => $hppAccount->id, 'debit' => $hppTotal, 'credit' => 0]);
                JournalDetail::create(['journal_entry_id' => $journal->id, 'account_id' => $persediaanAccount->id, 'debit' => 0, 'credit' => $hppTotal]);
            });

            return back()->with('success', 'Transaksi penjualan berhasil ditambahkan!');
        } catch (\Exception $e) {
            \Illuminate\Support\Facades\Log::error('Sale store error: ' . $e->getMessage());
            return back()->withInput()->withErrors(['db_error' => 'Gagal menyimpan transaksi: ' . $e->getMessage()]);
        }
    }

    private function ensureAccount($code, $name, $type)
    {
        return Account::updateOrCreate(
            ['code' => $code],
            ['name' => $name, 'type' => $type]
        );
    }

    public function update(Request $request, $id)
    {
        $request->validate([
            'date' => 'required|date',
            'product_id' => 'required|exists:products,id',
            'quantity' => 'required|integer|min:1',
            'total_price' => 'required|numeric|min:0',
        ]);

        try {
            \Illuminate\Support\Facades\DB::transaction(function () use ($request, $id) {
                $sale = Sale::findOrFail($id);
                $product = \App\Models\Product::findOrFail($request->product_id);

                // Bersihkan format angka (hapus titik pemisah ribuan jika ada)
                $cleanPrice = str_replace('.', '', $request->total_price);

                $data = $request->all();
                $data['item'] = $product->name;
                $data['total_price'] = (int) $cleanPrice;

                if (Auth::user()->role === 'admin' && $request->has('branch')) {
                    $data['branch'] = $request->branch;
                }
                
                $sale->update($data);

                // Recreate Journal Entry
                JournalEntry::where('reference_type', 'Sale')->where('reference_id', $sale->id)->delete();
                
                $kasAccount = Account::where('code', '101')->first();
                $penjualanAccount = Account::where('code', '401')->first();
                $hppAccount = Account::where('code', '501')->first();
                $persediaanAccount = Account::where('code', '102')->first();

                if ($kasAccount && $penjualanAccount && $hppAccount && $persediaanAccount) {
                    $journal = JournalEntry::create([
                        'date' => $sale->date,
                        'description' => 'Penjualan ' . $sale->item,
                        'reference_type' => 'Sale',
                        'reference_id' => $sale->id,
                        'branch' => $sale->branch,
                    ]);

                    JournalDetail::create(['journal_entry_id' => $journal->id, 'account_id' => $kasAccount->id, 'debit' => $sale->total_price, 'credit' => 0]);
                    JournalDetail::create(['journal_entry_id' => $journal->id, 'account_id' => $penjualanAccount->id, 'debit' => 0, 'credit' => $sale->total_price]);

                    $hppTotal = $sale->quantity * $product->purchase_price;
                    JournalDetail::create(['journal_entry_id' => $journal->id, 'account_id' => $hppAccount->id, 'debit' => $hppTotal, 'credit' => 0]);
                    JournalDetail::create(['journal_entry_id' => $journal->id, 'account_id' => $persediaanAccount->id, 'debit' => 0, 'credit' => $hppTotal]);
                }
            });

            return back()->with('success', 'Transaksi penjualan berhasil diperbarui!');
        } catch (\Exception $e) {
            \Illuminate\Support\Facades\Log::error('Sale update error: ' . $e->getMessage());
            return back()->withInput()->withErrors(['db_error' => 'Gagal memperbarui transaksi: ' . $e->getMessage()]);
        }
    }

    public function destroy($id)
    {
        $sale = Sale::findOrFail($id);
        JournalEntry::where('reference_type', 'Sale')->where('reference_id', $sale->id)->delete();
        $sale->delete();
        return back()->with('success', 'Transaksi penjualan berhasil dihapus!');
    }

    private function recalculateProductsFromRawMaterials($productId, $branch)
    {
        $product = \App\Models\Product::with('recipes.rawMaterial')->find($productId);
        if (!$product || $product->recipes->isEmpty()) {
            return;
        }

        $minStock = null;
        foreach ($product->recipes as $recipe) {
            $rm = $recipe->rawMaterial;
            if (!$rm || $recipe->quantity_needed <= 0) {
                continue;
            }
            $possibleAmount = floor($rm->stock_quantity / $recipe->quantity_needed);
            if ($minStock === null || $possibleAmount < $minStock) {
                $minStock = $possibleAmount;
            }
        }

        if ($minStock !== null && $minStock >= 0) {
            $stock = \App\Models\Stock::firstOrCreate(
                ['product_id' => $productId, 'branch' => $branch],
                ['quantity' => 0, 'unit' => 'Pcs']
            );
            $stock->quantity = $minStock;
            $stock->save();
        }
    }

    private function recalculateProductsFromRawMaterial($rawMaterialId, $branch)
    {
        $recipes = \App\Models\ProductRecipe::where('raw_material_id', $rawMaterialId)
            ->with(['product.recipes.rawMaterial'])
            ->get();

        foreach ($recipes as $recipe) {
            $product = $recipe->product;
            if (!$product) continue;

            $minStock = null;

            foreach ($product->recipes as $prodRecipe) {
                $rm = $prodRecipe->rawMaterial;
                if (!$rm || $prodRecipe->quantity_needed <= 0) continue;

                $rmStock = $rm->stock_quantity;
                $needed = $prodRecipe->quantity_needed;
                $possibleAmount = floor($rmStock / $needed);

                if ($minStock === null || $possibleAmount < $minStock) {
                    $minStock = $possibleAmount;
                }
            }

            if ($minStock !== null && $minStock >= 0) {
                $allBranches = \App\Models\Branch::all();
                foreach ($allBranches as $b) {
                    $stock = \App\Models\Stock::firstOrCreate(
                        ['product_id' => $product->id, 'branch' => $b->name],
                        ['quantity' => 0, 'unit' => 'Pcs']
                    );
                    $stock->quantity = $minStock;
                    $stock->save();
                }
            }
        }
    }
}
