<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\Sale;
use App\Models\Purchase;
use App\Models\Branch;
use App\Models\JournalEntry;
use App\Models\JournalDetail;
use App\Models\Stock;

class FinancialReportController extends Controller
{
    public function profitAndLoss(Request $request)
    {
        // Define branches dynamically
        $branches = Branch::pluck('name')->toArray();
        if (empty($branches)) {
            $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3']; // Fallback
        }
        
        $month = $request->get('month');
        $year = $request->get('year');

        // 1. Data Gabungan
        $jQuery = JournalDetail::with('journalEntry', 'account')
            ->whereHas('journalEntry', function($q) use ($month, $year) {
                if ($month) $q->whereMonth('date', $month);
                if ($year) $q->whereYear('date', $year);
            });

        $penjualan = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '401'); })->sum('credit');
        $hpp = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '501'); })->sum('debit');
        $labaKotor = $penjualan - $hpp;

        $opCostsDetails = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '502'); })->get();
        // Format to match existing view
        $opCostsTotal = $opCostsDetails->map(function($d) {
            $desc = str_replace('Biaya Operasional: ', '', $d->journalEntry->description);
            return (object)[
                'label' => $desc,
                'branch' => $d->journalEntry->branch,
                'amount' => $d->debit
            ];
        });
        $totalOpAmount = $opCostsTotal->sum('amount');
        $labaBersih = $labaKotor - $totalOpAmount;

        $dataTotal = [
            'penjualan' => $penjualan,
            'pembelian' => $hpp,
            'laba_kotor' => $labaKotor,
            'operational' => $opCostsTotal,
            'total_operational' => $totalOpAmount,
            'laba_bersih' => $labaBersih
        ];

        // 2. Per Branch Data
        $branchData = [];
        foreach ($branches as $branch) {
            $bJQuery = JournalDetail::with('journalEntry', 'account')
                ->whereHas('journalEntry', function($q) use ($month, $year, $branch) {
                    $q->where('branch', $branch);
                    if ($month) $q->whereMonth('date', $month);
                    if ($year) $q->whereYear('date', $year);
                });

            $bPenjualan = (clone $bJQuery)->whereHas('account', function($q) { $q->where('code', '401'); })->sum('credit');
            $bHpp = (clone $bJQuery)->whereHas('account', function($q) { $q->where('code', '501'); })->sum('debit');
            $bLabaKotor = $bPenjualan - $bHpp;

            $bOpCostsDetails = (clone $bJQuery)->whereHas('account', function($q) { $q->where('code', '502'); })->get();
            $bOpCostsTotal = $bOpCostsDetails->map(function($d) {
                $desc = str_replace('Biaya Operasional: ', '', $d->journalEntry->description);
                return (object)[
                    'label' => $desc,
                    'branch' => $d->journalEntry->branch,
                    'amount' => $d->debit
                ];
            });
            $bTotalOpAmount = $bOpCostsTotal->sum('amount');
            $bLabaBersih = $bLabaKotor - $bTotalOpAmount;

            $branchData[$branch] = [
                'penjualan' => $bPenjualan,
                'pembelian' => $bHpp,
                'laba_kotor' => $bLabaKotor,
                'operational' => $bOpCostsTotal,
                'total_operational' => $bTotalOpAmount,
                'laba_bersih' => $bLabaBersih
            ];
        }

        return view('neraca_laba_rugi', compact('dataTotal', 'branchData', 'branches'));
    }

    public function exportProfitAndLossPdf(Request $request)
    {
        $branches = Branch::pluck('name')->toArray();
        if (empty($branches)) {
            $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3']; // Fallback
        }
        
        $month = $request->get('month');
        $year = $request->get('year');
        $branchFilter = $request->get('branch');

        // Target branch calculation
        $targetBranch = $branchFilter ?: 'Total Gabungan';

        $jQuery = JournalDetail::with('journalEntry', 'account')
            ->whereHas('journalEntry', function($q) use ($month, $year, $branchFilter) {
                if ($branchFilter && $branchFilter !== 'Total Gabungan') {
                    $q->where('branch', $branchFilter);
                }
                if ($month) $q->whereMonth('date', $month);
                if ($year) $q->whereYear('date', $year);
            });

        $penjualan = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '401'); })->sum('credit');
        $hpp = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '501'); })->sum('debit');
        $labaKotor = $penjualan - $hpp;

        $opCostsDetails = (clone $jQuery)->whereHas('account', function($q) { $q->where('code', '502'); })->get();
        // Format to match existing view expectation
        $opCostsTotalData = $opCostsDetails->map(function($d) {
            $desc = str_replace('Biaya Operasional: ', '', $d->journalEntry->description);
            return (object)[
                'label' => $desc,
                'branch' => $d->journalEntry->branch,
                'amount' => $d->debit
            ];
        });
        
        $totalOpAmount = $opCostsTotalData->sum('amount');
        $labaBersih = $labaKotor - $totalOpAmount;

        $data = [
            'penjualan' => $penjualan,
            'pembelian' => $hpp,
            'laba_kotor' => $labaKotor,
            'operational' => $opCostsTotalData,
            'total_operational' => $totalOpAmount,
            'laba_bersih' => $labaBersih,
            'branch' => $targetBranch,
            'month' => $month,
            'year' => $year
        ];

        $pdf = \Barryvdh\DomPDF\Facade\Pdf::loadView('reports.neraca_laba_rugi_pdf', $data);
        return $pdf->download('laporan_neraca_laba_rugi_' . date('Y-m-d') . '.pdf');
    }

    public function generalLedger()
    {
        $branches = Branch::pluck('name')->toArray();
        if (empty($branches)) {
            $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3']; // Fallback
        }
        
        // 1. Total Gabungan
        // Filter only 'Kas' account (101) to match existing simplified Ledger layout
        $kasDetails = JournalDetail::whereHas('account', function($q) {
            $q->where('code', '101');
        })->with('journalEntry')->get();

        $transactionsTotal = $kasDetails->map(function($d) {
            return [
                'date' => $d->journalEntry->date,
                'account' => 'Kas',
                'desc' => $d->journalEntry->description,
                'debit' => $d->debit,
                'credit' => $d->credit
            ];
        });

        // Initial Balance dari nilai stok saat ini
        $initialBalance = $this->calculateModalFromStock();
        $ledgerTotal = $this->processLedger($transactionsTotal, $initialBalance, 'Modal dari Stok');

        // 2. Per Branch
        $branchLedgers = [];
        foreach ($branches as $branch) {
            $initialBranchBalance = $this->calculateModalFromStock($branch);
            $bKasDetails = JournalDetail::whereHas('account', function($q) {
                $q->where('code', '101');
            })->whereHas('journalEntry', function($q) use ($branch) {
                $q->where('branch', $branch);
            })->with('journalEntry')->get();

            $bTransactions = $bKasDetails->map(function($d) {
                return [
                    'date' => $d->journalEntry->date,
                    'account' => 'Kas',
                    'desc' => $d->journalEntry->description,
                    'debit' => $d->debit,
                    'credit' => $d->credit
                ];
            });

            $branchLedgers[$branch] = $this->processLedger($bTransactions, $initialBranchBalance, 'Modal dari Stok ' . $branch);
        }

        return view('buku_besar', compact('ledgerTotal', 'branchLedgers', 'branches'));
    }

    private function processLedger($transactions, $initialBalance, $initialDesc)
    {
        $ledger = collect();
        
        // Add Initial Transaction
        $ledger->push([
            'date' => '2025-09-01', // Example date matching mockup
            'account' => 'Kas',
            'desc' => $initialDesc,
            'debit' => $initialBalance,
            'credit' => 0,
            'balance' => $initialBalance
        ]);

        $sortedTrans = $transactions->sortBy('date');
        $currentBalance = $initialBalance;

        foreach ($sortedTrans as $t) {
            $currentBalance += $t['debit'];
            $currentBalance -= $t['credit'];
            
            $ledger->push([
                'date' => $t['date'],
                'account' => $t['account'],
                'desc' => $t['desc'],
                'debit' => $t['debit'],
                'credit' => $t['credit'],
                'balance' => $currentBalance
            ]);
        }

        return $ledger;
    }

    public function generalJournal()
    {
        $branches = Branch::pluck('name')->toArray();
        if (empty($branches)) {
            $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3']; // Fallback
        }
        
        // 1. Total Gabungan
        $journalTotal = collect();
        
        $details = JournalDetail::with('journalEntry', 'account')
            ->join('journal_entries', 'journal_details.journal_entry_id', '=', 'journal_entries.id')
            ->orderBy('journal_entries.date')
            ->orderBy('journal_entries.id')
            ->orderBy('journal_details.credit') // debit first
            ->select('journal_details.*')
            ->get();

        foreach($details as $d) {
            $journalTotal->push([
                'date' => $d->journalEntry->date, 
                'desc' => $d->credit > 0 ? '  ' . $d->account->name : $d->account->name, 
                'reff' => $d->account->code, 
                'debit' => $d->debit, 
                'credit' => $d->credit
            ]);
        }

        // 2. Per Branch Data
        $branchJournals = [];
        foreach ($branches as $branch) {
            $journal = collect();

            $bDetails = JournalDetail::with('journalEntry', 'account')
                ->join('journal_entries', 'journal_details.journal_entry_id', '=', 'journal_entries.id')
                ->where('journal_entries.branch', $branch)
                ->orderBy('journal_entries.date')
                ->orderBy('journal_entries.id')
                ->orderBy('journal_details.credit') // debit first
                ->select('journal_details.*')
                ->get();

            foreach($bDetails as $d) {
                $journal->push([
                    'date' => $d->journalEntry->date, 
                    'desc' => $d->credit > 0 ? '  ' . $d->account->name : $d->account->name, 
                    'reff' => $d->account->code, 
                    'debit' => $d->debit, 
                    'credit' => $d->credit
                ]);
            }
            
            $branchJournals[$branch] = $journal;
        }

        return view('jurnal_umum', compact('journalTotal', 'branchJournals', 'branches'));
    }

    public function equityStatement(Request $request)
    {
        $branches = Branch::pluck('name')->toArray();
        if (empty($branches)) $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3'];

        // Laba Bersih = Penjualan (401) - HPP (501) - Biaya (502)
        $penjualan = JournalDetail::whereHas('account', function($q) { $q->where('code', '401'); })->sum('credit');
        $hpp = JournalDetail::whereHas('account', function($q) { $q->where('code', '501'); })->sum('debit');
        $biaya = JournalDetail::whereHas('account', function($q) { $q->where('code', '502'); })->sum('debit');
        $labaBersih = $penjualan - $hpp - $biaya;

        // Modal berasal dari nilai stok saat ini berdasarkan biaya perolehan (harga beli),
        // karena sistem belum punya akun modal nyata.
        $modalAwal = $this->calculateModalFromStock();

        $modalAkhir = $modalAwal + $labaBersih;

        $data = [
            'modal_awal' => $modalAwal,
            'laba_bersih' => $labaBersih,
            'prive' => 0,
            'modal_akhir' => $modalAkhir
        ];

        return view('perubahan_modal', compact('data', 'branches'));
    }

    public function balanceSheet(Request $request)
    {
        $branches = Branch::pluck('name')->toArray();
        if (empty($branches)) $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3'];

        // Assets
        $kas = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })->sum('debit') - JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })->sum('credit');
        
        // Persediaan dari journal (Debit = Awal Persediaan, Credit = Penjualan HPP)
        $persediaan = JournalDetail::whereHas('account', function($q) { $q->where('code', '102'); })->sum('debit') - JournalDetail::whereHas('account', function($q) { $q->where('code', '102'); })->sum('credit');
        
        $totalAset = $kas + $persediaan;

        // Liabilities
        $hutang = 0; // We don't have liability accounts seeded yet

        // Equity
        $penjualan = JournalDetail::whereHas('account', function($q) { $q->where('code', '401'); })->sum('credit');
        $hpp = JournalDetail::whereHas('account', function($q) { $q->where('code', '501'); })->sum('debit');
        $biaya = JournalDetail::whereHas('account', function($q) { $q->where('code', '502'); })->sum('debit');
        $labaBersih = $penjualan - $hpp - $biaya;

        // Modal berasal dari nilai stok saat ini berdasarkan biaya perolehan (harga beli),
        // karena sistem belum punya akun modal nyata.
        $modalAwal = $this->calculateModalFromStock();
        $modalAkhir = $modalAwal + $labaBersih;

        $totalPasiva = $hutang + $modalAkhir;

        $data = [
            'kas' => $kas,
            'persediaan' => $persediaan,
            'total_aset' => $totalAset,
            'hutang' => $hutang,
            'modal_akhir' => $modalAkhir,
            'total_pasiva' => $totalPasiva
        ];

        return view('neraca_keuangan', compact('data', 'branches'));
    }

    private function calculateModalFromStock($branch = null)
    {
        $query = Stock::query()->with('product');

        if ($branch) {
            $query->where('branch', $branch);
        }

        return (float) $query->get()->sum(function ($stock) {
            $product = $stock->product;
            if (!$product) {
                return 0;
            }

            $quantity = (float) $stock->quantity;
            $purchasePrice = (float) $product->purchase_price;

            return $quantity > 0 ? $quantity * $purchasePrice : 0;
        });
    }

    public function cashFlow(Request $request)
    {
        $branches = Branch::pluck('name')->toArray();
        if (empty($branches)) $branches = ['Cabang 1', 'Cabang 2', 'Cabang 3'];

        // Penerimaan dari Penjualan (Debit Kas dari Jurnal Penjualan)
        $penerimaanPenjualan = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })
            ->whereHas('journalEntry', function($q) { $q->where('reference_type', 'Sale'); })->sum('debit');

        // Pengeluaran Pembelian (Kredit Kas dari Pembelian)
        $pengeluaranPembelian = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })
            ->whereHas('journalEntry', function($q) { $q->where('reference_type', 'Purchase'); })->sum('credit');

        // Pengeluaran Biaya Operasional (Kredit Kas dari Biaya Operasional)
        $pengeluaranOperasional = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })
            ->whereHas('journalEntry', function($q) { $q->where('reference_type', 'OperationalCost'); })->sum('credit');

        // Modal berasal dari stok, sehingga tidak ada setoran modal terpisah dalam arus kas
        $setoranModal = 0;

        $arusKasOperasi = $penerimaanPenjualan - $pengeluaranPembelian - $pengeluaranOperasional;
        $arusKasPendanaan = $setoranModal;
        $kenaikanKas = $arusKasOperasi + $arusKasPendanaan;

        // Saldo Kas Akhir
        $saldoKas = JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })->sum('debit') - JournalDetail::whereHas('account', function($q) { $q->where('code', '101'); })->sum('credit');

        $data = [
            'penerimaan_penjualan' => $penerimaanPenjualan,
            'pengeluaran_pembelian' => $pengeluaranPembelian,
            'pengeluaran_operasional' => $pengeluaranOperasional,
            'arus_kas_operasi' => $arusKasOperasi,
            'setoran_modal' => $setoranModal,
            'arus_kas_pendanaan' => $arusKasPendanaan,
            'kenaikan_kas' => $kenaikanKas,
            'saldo_kas' => $saldoKas
        ];

        return view('arus_kas', compact('data', 'branches'));
    }
}
