<?php

namespace App\Helpers;

use App\Models\ChartOfAccount;
use App\Models\JournalEntry;
use App\Models\AccountTransaction;
use Carbon\Carbon;

class AccountingHelper
{
    /**
     * Generate voucher number
     */
    public static function generateVoucherNo($type = 'journal')
    {
        $prefix = 'JV'; // Journal Voucher
        
        if ($type == 'receipt') {
            $prefix = 'RCPT';
        } elseif ($type == 'payment') {
            $prefix = 'PMT';
        } elseif ($type == 'contra') {
            $prefix = 'CONTRA';
        } elseif ($type == 'saving') {
            $prefix = 'SVG';
        } elseif ($type == 'loan') {
            $prefix = 'LN';
        }
        
        $date = date('Ymd');
        $lastVoucher = JournalEntry::where('voucher_no', 'like', $prefix . '-' . $date . '%')
            ->orderBy('voucher_no', 'desc')
            ->first();
        
        if ($lastVoucher) {
            $lastNumber = (int) substr($lastVoucher->voucher_no, -3);
            $nextNumber = str_pad($lastNumber + 1, 3, '0', STR_PAD_LEFT);
        } else {
            $nextNumber = '001';
        }
        
        return $prefix . '-' . $date . '-' . $nextNumber;
    }
    
    /**
     * Create journal entry for saving collection
     */
    public static function createSavingCollectionEntry($member, $amount, $monthYear, $remarks = null)
    {
        $voucherNo = self::generateVoucherNo('saving');
        
        $journal = JournalEntry::create([
            'voucher_no' => $voucherNo,
            'transaction_date' => now(),
            'transaction_type' => 'saving_collection',
            'narration' => "সঞ্চয় সংগ্রহ - {$member->name} - {$monthYear}",
            'remarks' => $remarks,
            'created_by' => auth()->id(),
            'total_debit' => $amount,
            'total_credit' => $amount
        ]);
        
        // Debit: Cash/Bank account
        $journal->items()->create([
            'account_id' => ChartOfAccount::where('account_subtype', 'cash_in_hand')->first()->id,
            'debit' => $amount,
            'description' => "সঞ্চয় সংগ্রহ - {$member->name}"
        ]);
        
        // Credit: Saving Collection account
        $journal->items()->create([
            'account_id' => ChartOfAccount::where('account_code', '4210')->first()->id,
            'credit' => $amount,
            'description' => "সঞ্চয় সংগ্রহ - {$member->name}"
        ]);
        
        return $journal;
    }
    
    /**
     * Create journal entry for loan disbursement
     */
    public static function createLoanDisbursementEntry($loan, $amount, $remarks = null)
    {
        $voucherNo = self::generateVoucherNo('loan');
        
        $journal = JournalEntry::create([
            'voucher_no' => $voucherNo,
            'transaction_date' => now(),
            'transaction_type' => 'loan_disbursement',
            'narration' => "ঋণ বিতরণ - {$loan->member->name} - লোন নং: {$loan->loan_number}",
            'remarks' => $remarks,
            'created_by' => auth()->id(),
            'total_debit' => $amount,
            'total_credit' => $amount
        ]);
        
        // Debit: Loan Receivable account
        $journal->items()->create([
            'account_id' => ChartOfAccount::where('account_subtype', 'receivable')->first()->id,
            'debit' => $amount,
            'description' => "ঋণ বিতরণ - {$loan->member->name}"
        ]);
        
        // Credit: Cash/Bank account
        $journal->items()->create([
            'account_id' => ChartOfAccount::where('account_subtype', 'cash_in_hand')->first()->id,
            'credit' => $amount,
            'description' => "ঋণ বিতরণ - {$loan->member->name}"
        ]);
        
        return $journal;
    }
    
    /**
     * Create journal entry for loan repayment
     */
    public static function createLoanRepaymentEntry($loan, $principal, $interest, $remarks = null)
    {
        $voucherNo = self::generateVoucherNo('loan');
        $totalAmount = $principal + $interest;
        
        $journal = JournalEntry::create([
            'voucher_no' => $voucherNo,
            'transaction_date' => now(),
            'transaction_type' => 'loan_repayment',
            'narration' => "ঋণ পরিশোধ - {$loan->member->name}",
            'remarks' => $remarks,
            'created_by' => auth()->id(),
            'total_debit' => $totalAmount,
            'total_credit' => $totalAmount
        ]);
        
        // Debit: Cash/Bank account
        $journal->items()->create([
            'account_id' => ChartOfAccount::where('account_subtype', 'cash_in_hand')->first()->id,
            'debit' => $totalAmount,
            'description' => "ঋণ পরিশোধ - {$loan->member->name}"
        ]);
        
        // Credit: Loan Receivable (Principal)
        $journal->items()->create([
            'account_id' => ChartOfAccount::where('account_subtype', 'receivable')->first()->id,
            'credit' => $principal,
            'description' => "আসল পরিশোধ - {$loan->member->name}"
        ]);
        
        // Credit: Interest Income
        $journal->items()->create([
            'account_id' => ChartOfAccount::where('account_code', '4310')->first()->id,
            'credit' => $interest,
            'description' => "সুদ আয় - {$loan->member->name}"
        ]);
        
        return $journal;
    }
    
    /**
     * Get trial balance for a date
     */
    public static function getTrialBalance($asOfDate = null)
    {
        if (!$asOfDate) {
            $asOfDate = now();
        }
        
        $accounts = ChartOfAccount::active()->get();
        $trialBalance = [];
        
        foreach ($accounts as $account) {
            $balance = $account->getBalanceAsOf($asOfDate);
            
            if ($balance != 0) {
                $trialBalance[] = [
                    'account_code' => $account->account_code,
                    'account_name' => $account->account_name,
                    'account_type' => $account->account_type,
                    'debit' => $account->balance_type == 'debit' ? $balance : 0,
                    'credit' => $account->balance_type == 'credit' ? $balance : 0,
                ];
            }
        }
        
        $totalDebit = collect($trialBalance)->sum('debit');
        $totalCredit = collect($trialBalance)->sum('credit');
        
        return [
            'data' => $trialBalance,
            'total_debit' => $totalDebit,
            'total_credit' => $totalCredit,
            'as_of_date' => $asOfDate
        ];
    }
    
    /**
     * Get balance sheet data
     */
    public static function getBalanceSheet($asOfDate = null)
    {
        if (!$asOfDate) {
            $asOfDate = now();
        }
        
        $accounts = ChartOfAccount::active()->get();
        
        $assets = [];
        $liabilities = [];
        $equity = [];
        
        $totalAssets = 0;
        $totalLiabilities = 0;
        $totalEquity = 0;
        
        foreach ($accounts as $account) {
            $balance = $account->getBalanceAsOf($asOfDate);
            
            if ($balance != 0) {
                switch ($account->account_type) {
                    case 'asset':
                        $assets[] = [
                            'code' => $account->account_code,
                            'name' => $account->account_name,
                            'balance' => $balance
                        ];
                        $totalAssets += $balance;
                        break;
                        
                    case 'liability':
                        $liabilities[] = [
                            'code' => $account->account_code,
                            'name' => $account->account_name,
                            'balance' => $balance
                        ];
                        $totalLiabilities += $balance;
                        break;
                        
                    case 'equity':
                        $equity[] = [
                            'code' => $account->account_code,
                            'name' => $account->account_name,
                            'balance' => $balance
                        ];
                        $totalEquity += $balance;
                        break;
                }
            }
        }
        
        return [
            'assets' => $assets,
            'liabilities' => $liabilities,
            'equity' => $equity,
            'total_assets' => $totalAssets,
            'total_liabilities' => $totalLiabilities,
            'total_equity' => $totalEquity,
            'as_of_date' => $asOfDate
        ];
    }
    
    /**
     * Get income statement data
     */
    public static function getIncomeStatement($fromDate, $toDate)
    {
        $revenueAccounts = ChartOfAccount::where('account_type', 'revenue')->get();
        $expenseAccounts = ChartOfAccount::where('account_type', 'expense')->get();
        
        $revenues = [];
        $expenses = [];
        
        $totalRevenue = 0;
        $totalExpense = 0;
        
        foreach ($revenueAccounts as $account) {
            $transactions = $account->transactions()
                ->whereBetween('transaction_date', [$fromDate, $toDate])
                ->get();
            
            $revenueAmount = 0;
            foreach ($transactions as $transaction) {
                if ($transaction->transaction_type == 'credit') {
                    $revenueAmount += $transaction->amount;
                } else {
                    $revenueAmount -= $transaction->amount;
                }
            }
            
            if ($revenueAmount != 0) {
                $revenues[] = [
                    'code' => $account->account_code,
                    'name' => $account->account_name,
                    'amount' => $revenueAmount
                ];
                $totalRevenue += $revenueAmount;
            }
        }
        
        foreach ($expenseAccounts as $account) {
            $transactions = $account->transactions()
                ->whereBetween('transaction_date', [$fromDate, $toDate])
                ->get();
            
            $expenseAmount = 0;
            foreach ($transactions as $transaction) {
                if ($transaction->transaction_type == 'debit') {
                    $expenseAmount += $transaction->amount;
                } else {
                    $expenseAmount -= $transaction->amount;
                }
            }
            
            if ($expenseAmount != 0) {
                $expenses[] = [
                    'code' => $account->account_code,
                    'name' => $account->account_name,
                    'amount' => $expenseAmount
                ];
                $totalExpense += $expenseAmount;
            }
        }
        
        $netIncome = $totalRevenue - $totalExpense;
        
        return [
            'revenues' => $revenues,
            'expenses' => $expenses,
            'total_revenue' => $totalRevenue,
            'total_expense' => $totalExpense,
            'net_income' => $netIncome,
            'from_date' => $fromDate,
            'to_date' => $toDate
        ];
    }
}