<?php

namespace App\Http\Controllers;

use App\Models\ChartOfAccount;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class FinancialStatementController extends Controller
{
    /**
     * ফাইন্যান্সিয়াল স্টেটমেন্টস ইনডেক্স
     */
    public function index()
    {
        return view('accounting.financial-statements.index');
    }

    /**
     * ব্যালেন্স শীট
     */
    public function balanceSheet(Request $request)
    {
        $date = $request->get('as_of_date', now()->format('Y-m-d'));
        
        // Assets
        $currentAssets = ChartOfAccount::where('type', 'asset')
            ->where('sub_type', 'current_asset')
            ->active()
            ->get();
            
        $fixedAssets = ChartOfAccount::where('type', 'asset')
            ->where('sub_type', 'fixed_asset')
            ->active()
            ->get();
            
        $otherAssets = ChartOfAccount::where('type', 'asset')
            ->where('sub_type', 'other_asset')
            ->active()
            ->get();
        
        // Liabilities
        $currentLiabilities = ChartOfAccount::where('type', 'liability')
            ->where('sub_type', 'current_liability')
            ->active()
            ->get();
            
        $longTermLiabilities = ChartOfAccount::where('type', 'liability')
            ->where('sub_type', 'long_term_liability')
            ->active()
            ->get();
        
        // Equity
        $capitalAccounts = ChartOfAccount::where('type', 'equity')
            ->where('sub_type', 'capital')
            ->active()
            ->get();
            
        $retainedEarnings = ChartOfAccount::where('type', 'equity')
            ->where('sub_type', 'retained_earnings')
            ->active()
            ->get();
        
        // Calculate totals
        $totalCurrentAssets = $currentAssets->sum('current_balance');
        $totalFixedAssets = $fixedAssets->sum('current_balance');
        $totalOtherAssets = $otherAssets->sum('current_balance');
        $totalAssets = $totalCurrentAssets + $totalFixedAssets + $totalOtherAssets;
        
        $totalCurrentLiabilities = $currentLiabilities->sum('current_balance');
        $totalLongTermLiabilities = $longTermLiabilities->sum('current_balance');
        $totalLiabilities = $totalCurrentLiabilities + $totalLongTermLiabilities;
        
        $totalCapital = $capitalAccounts->sum('current_balance');
        $totalRetainedEarnings = $retainedEarnings->sum('current_balance');
        $totalEquity = $totalCapital + $totalRetainedEarnings;
        
        $totalLiabilitiesAndEquity = $totalLiabilities + $totalEquity;
        
        return view('accounting.financial-statements.balance-sheet', compact(
            'date',
            'currentAssets', 'fixedAssets', 'otherAssets',
            'currentLiabilities', 'longTermLiabilities',
            'capitalAccounts', 'retainedEarnings',
            'totalCurrentAssets', 'totalFixedAssets', 'totalOtherAssets', 'totalAssets',
            'totalCurrentLiabilities', 'totalLongTermLiabilities', 'totalLiabilities',
            'totalCapital', 'totalRetainedEarnings', 'totalEquity',
            'totalLiabilitiesAndEquity'
        ));
    }

    /**
     * ইনকাম স্টেটমেন্ট (আয় বিবরণী)
     */
    public function incomeStatement(Request $request)
    {
        $fromDate = $request->get('from_date', now()->startOfMonth()->format('Y-m-d'));
        $toDate = $request->get('to_date', now()->format('Y-m-d'));
        
        // Income
        $operatingIncome = $this->getAccountTransactions('income', 'operating_income', $fromDate, $toDate);
        $nonOperatingIncome = $this->getAccountTransactions('income', 'non_operating_income', $fromDate, $toDate);
        
        // Expenses
        $operatingExpenses = $this->getAccountTransactions('expense', 'operating_expense', $fromDate, $toDate);
        $nonOperatingExpenses = $this->getAccountTransactions('expense', 'non_operating_expense', $fromDate, $toDate);
        
        // Calculate totals
        $totalOperatingIncome = $operatingIncome['total'];
        $totalNonOperatingIncome = $nonOperatingIncome['total'];
        $totalIncome = $totalOperatingIncome + $totalNonOperatingIncome;
        
        $totalOperatingExpenses = $operatingExpenses['total'];
        $totalNonOperatingExpenses = $nonOperatingExpenses['total'];
        $totalExpenses = $totalOperatingExpenses + $totalNonOperatingExpenses;
        
        $netIncome = $totalIncome - $totalExpenses;
        
        return view('accounting.financial-statements.income-statement', compact(
            'fromDate', 'toDate',
            'operatingIncome', 'nonOperatingIncome',
            'operatingExpenses', 'nonOperatingExpenses',
            'totalOperatingIncome', 'totalNonOperatingIncome', 'totalIncome',
            'totalOperatingExpenses', 'totalNonOperatingExpenses', 'totalExpenses',
            'netIncome'
        ));
    }

    /**
     * ট্রায়াল ব্যালেন্স
     */
    public function trialBalance(Request $request)
    {
        $date = $request->get('as_of_date', now()->format('Y-m-d'));
        
        $accounts = ChartOfAccount::active()
            ->with(['journalEntryItems' => function($query) use ($date) {
                $query->whereHas('journalEntry', function($q) use ($date) {
                    $q->where('entry_date', '<=', $date)
                      ->where('status', 'posted');
                });
            }])
            ->get()
            ->map(function($account) {
                $totalDebit = $account->journalEntryItems->sum('debit');
                $totalCredit = $account->journalEntryItems->sum('credit');
                
                // Calculate balance based on account type
                if ($account->type == 'asset' || $account->type == 'expense') {
                    $balance = $account->opening_balance + $totalDebit - $totalCredit;
                } else {
                    $balance = $account->opening_balance + $totalCredit - $totalDebit;
                }
                
                return [
                    'account' => $account,
                    'debit' => $balance > 0 && ($account->type == 'asset' || $account->type == 'expense') ? abs($balance) : 0,
                    'credit' => $balance > 0 && ($account->type == 'liability' || $account->type == 'equity' || $account->type == 'income') ? abs($balance) : 0,
                    'opening_balance' => $account->opening_balance,
                    'current_balance' => $balance
                ];
            });
        
        $totalDebit = $accounts->sum('debit');
        $totalCredit = $accounts->sum('credit');
        
        return view('accounting.financial-statements.trial-balance', compact(
            'accounts', 'totalDebit', 'totalCredit', 'date'
        ));
    }

    /**
     * ক্যাশ ফ্লো স্টেটমেন্ট
     */
    public function cashFlow(Request $request)
    {
        $fromDate = $request->get('from_date', now()->startOfMonth()->format('Y-m-d'));
        $toDate = $request->get('to_date', now()->format('Y-m-d'));
        
        // Operating Activities
        $operatingActivities = $this->getCashFlowActivities('operating', $fromDate, $toDate);
        
        // Investing Activities
        $investingActivities = $this->getCashFlowActivities('investing', $fromDate, $toDate);
        
        // Financing Activities
        $financingActivities = $this->getCashFlowActivities('financing', $fromDate, $toDate);
        
        // Calculate totals
        $netCashFromOperating = $operatingActivities['inflows'] - $operatingActivities['outflows'];
        $netCashFromInvesting = $investingActivities['inflows'] - $investingActivities['outflows'];
        $netCashFromFinancing = $financingActivities['inflows'] - $financingActivities['outflows'];
        
        $netIncreaseInCash = $netCashFromOperating + $netCashFromInvesting + $netCashFromFinancing;
        
        // Opening and closing cash balance
        $cashAccount = ChartOfAccount::where('code', 'like', '1001%')->first();
        $openingCashBalance = $cashAccount ? $cashAccount->opening_balance : 0;
        
        // Calculate closing balance
        $closingCashBalance = $openingCashBalance + $netIncreaseInCash;
        
        return view('accounting.financial-statements.cash-flow', compact(
            'fromDate', 'toDate',
            'operatingActivities', 'investingActivities', 'financingActivities',
            'netCashFromOperating', 'netCashFromInvesting', 'netCashFromFinancing',
            'netIncreaseInCash', 'openingCashBalance', 'closingCashBalance'
        ));
    }

    /**
     * ফাইন্যান্সিয়াল স্টেটমেন্ট প্রিন্ট
     */
    public function print(Request $request, $type)
    {
        switch ($type) {
            case 'balance-sheet':
                return $this->balanceSheet($request);
            case 'income-statement':
                return $this->incomeStatement($request);
            case 'trial-balance':
                return $this->trialBalance($request);
            case 'cash-flow':
                return $this->cashFlow($request);
            default:
                abort(404);
        }
    }

    /**
     * হেল্পার: অ্যাকাউন্ট ট্রানজ্যাকশন সংগ্রহ
     */
    private function getAccountTransactions($type, $subType, $fromDate, $toDate)
    {
        $accounts = ChartOfAccount::where('type', $type)
            ->where('sub_type', $subType)
            ->active()
            ->get();
        
        $transactions = [];
        $total = 0;
        
        foreach ($accounts as $account) {
            $items = $account->journalEntryItems()
                ->whereHas('journalEntry', function($query) use ($fromDate, $toDate) {
                    $query->whereBetween('entry_date', [$fromDate, $toDate])
                          ->where('status', 'posted');
                })
                ->get();
            
            $accountTotal = $items->sum(function($item) use ($type) {
                if ($type == 'income') {
                    return $item->credit - $item->debit;
                } else {
                    return $item->debit - $item->credit;
                }
            });
            
            if ($accountTotal != 0) {
                $transactions[] = [
                    'account' => $account,
                    'amount' => abs($accountTotal),
                    'items' => $items
                ];
                $total += $accountTotal;
            }
        }
        
        return [
            'transactions' => $transactions,
            'total' => abs($total)
        ];
    }

    /**
     * হেল্পার: ক্যাশ ফ্লো অ্যাক্টিভিটি সংগ্রহ
     */
    private function getCashFlowActivities($activityType, $fromDate, $toDate)
    {
        // This is a simplified version
        // In a real application, you would map accounts to activity types
        
        $inflows = 0;
        $outflows = 0;
        $transactions = [];
        
        // Sample logic - you need to customize this based on your chart of accounts
        switch ($activityType) {
            case 'operating':
                // Operating activities: income and expense accounts
                $accounts = ChartOfAccount::whereIn('type', ['income', 'expense'])
                    ->active()
                    ->get();
                break;
            case 'investing':
                // Investing activities: fixed asset purchases/sales
                $accounts = ChartOfAccount::where('sub_type', 'fixed_asset')
                    ->active()
                    ->get();
                break;
            case 'financing':
                // Financing activities: equity and long-term liabilities
                $accounts = ChartOfAccount::whereIn('sub_type', ['capital', 'long_term_liability'])
                    ->active()
                    ->get();
                break;
        }
        
        foreach ($accounts as $account) {
            $items = $account->journalEntryItems()
                ->whereHas('journalEntry', function($query) use ($fromDate, $toDate) {
                    $query->whereBetween('entry_date', [$fromDate, $toDate])
                          ->where('status', 'posted');
                })
                ->get();
            
            foreach ($items as $item) {
                $amount = $item->debit > 0 ? $item->debit : $item->credit;
                
                // Determine if it's inflow or outflow
                // This logic depends on your chart of accounts structure
                if (($activityType == 'operating' && $account->type == 'income') ||
                    ($activityType == 'investing' && $item->credit > 0) ||
                    ($activityType == 'financing' && $item->credit > 0)) {
                    $inflows += $amount;
                    $type = 'inflow';
                } else {
                    $outflows += $amount;
                    $type = 'outflow';
                }
                
                $transactions[] = [
                    'date' => $item->journalEntry->entry_date,
                    'account' => $account,
                    'description' => $item->description ?? $item->journalEntry->narration,
                    'amount' => $amount,
                    'type' => $type
                ];
            }
        }
        
        return [
            'inflows' => $inflows,
            'outflows' => $outflows,
            'transactions' => $transactions
        ];
    }
}