<?php

namespace App\Http\Controllers;

use App\Models\SavingsAccount;
use App\Models\Client;
use App\Models\Loan;
use App\Models\SavingsTransaction;
use App\Models\Receipt;
use App\Models\CashTransaction;
use App\Models\CashbookTempEntry; // Add this
use App\Models\GeneralJournalTemp; // Add this
use App\Models\JournalEntry;
use App\Models\JournalEntryItem;
use App\Models\GeneralLedger; // Add this
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Barryvdh\DomPDF\Facade\Pdf;

/**
 * Savings Account Management Controller
 *
 * Handles all savings account operations including CRUD operations, transactions,
 * deposits, withdrawals, interest calculations, and reporting for the savings management system.
 *
 * Features:
 * - Savings account creation and management
 * - Deposit and withdrawal processing
 * - Transaction tracking and history
 * - Interest calculation and posting
 * - Loan linking and unlinking
 * - PDF reporting and printing
 * - Cash book and journal entry integration
 *
 * @package App\Http\Controllers
 */
class SavingsAccountController extends Controller
{
    /**
     * Display savings accounts list with filtering and search
     */
    public function index(Request $request)
    {
        $query = SavingsAccount::with(['client', 'creator', 'loans']);

        // Apply search filter
        if ($search = $request->search) {
            $query->where(function($q) use ($search) {
                $q->where('account_number', 'like', "%{$search}%")
                  ->orWhereHas('client', function($q) use ($search) {
                      $q->where('first_name', 'like', "%{$search}%")
                        ->orWhere('last_name', 'like', "%{$search}%")
                        ->orWhere('client_number', 'like', "%{$search}%");
                  });
            });
        }

        // Apply filters using arrow functions
        $query->when($request->status, fn($q) => $q->where('status', $request->status))
              ->when($request->type, fn($q) => $q->where('type', $request->type))
              ->when($request->has_loans === 'yes', fn($q) => $q->has('loans'))
              ->when($request->has_loans === 'no', fn($q) => $q->doesntHave('loans'));

        $savingsAccounts = $query->latest()->paginate(20);

        return view('savings.accounts.index', compact('savingsAccounts'));
    }

    /**
     * Show the form for creating a new savings account
     */
    public function create()
    {
        try {
            $clients = Client::where('status', 'active')->orderBy('first_name')->get();
            $products = $this->getSavingsProducts();

            return view('savings.accounts.create', compact('clients', 'products'));
        } catch (\Exception $e) {
            Log::error('Error loading savings account creation form', ['error' => $e->getMessage()]);
            return back()->with('error', 'Error loading savings account form: ' . $e->getMessage());
        }
    }

    /**
     * Get savings products - handles both database and default products
     */
    private function getSavingsProducts()
    {
        try {
            if (class_exists('App\\Models\\SavingsProduct')) {
                $dbProducts = \App\Models\SavingsProduct::where('status', 'active')->get();

                // Convert to array format for consistency
                return $dbProducts->map(function($product) {
                    return [
                        'name' => $product->name,
                        'type' => $product->type,
                        'interest_rate' => $product->interest_rate,
                        'minimum_balance' => $product->minimum_balance,
                        'interest_calculation' => $product->interest_calculation,
                    ];
                })->toArray();
            }
        } catch (\Exception $e) {
            Log::warning('Savings products table not found, using default products', [
                'error' => $e->getMessage()
            ]);
        }

        // Default product options as arrays
        return [
            [
                'name' => 'Regular Savings',
                'type' => 'savings',
                'interest_rate' => 2.5,
                'minimum_balance' => 100,
                'interest_calculation' => 'monthly'
            ],
            [
                'name' => 'Fixed Deposit',
                'type' => 'fixed_deposit',
                'interest_rate' => 5.0,
                'minimum_balance' => 1000,
                'interest_calculation' => 'monthly'
            ],
            [
                'name' => 'Current Account',
                'type' => 'current',
                'interest_rate' => 0.5,
                'minimum_balance' => 500,
                'interest_calculation' => 'monthly'
            ]
        ];
    }

    /**
     * Store a newly created savings account
     */
    public function store(Request $request)
    {
        $validated = $request->validate([
            'client_id' => 'required|exists:clients,id',
            'product_name' => 'required|string|max:255',
            'type' => 'required|in:savings,fixed_deposit,current',
            'opening_balance' => 'required|numeric|min:0',
            'interest_rate' => 'required|numeric|min:0|max:100',
            'minimum_balance' => 'required|numeric|min:0',
            'opening_date' => 'required|date',
            'notes' => 'nullable|string',
        ]);

        try {
            DB::beginTransaction();

            $accountNumber = $this->generateAccountNumber();
            $account = SavingsAccount::create([
                'account_number' => $accountNumber,
                'client_id' => $validated['client_id'],
                'product_name' => $validated['product_name'],
                'type' => $validated['type'],
                'opening_balance' => $validated['opening_balance'],
                'current_balance' => $validated['opening_balance'],
                'minimum_balance' => $validated['minimum_balance'],
                'interest_rate' => $validated['interest_rate'],
                'interest_calculation' => 'monthly',
                'opening_date' => $validated['opening_date'],
                'status' => 'active',
                'notes' => $validated['notes'],
                'created_by' => Auth::id(),
            ]);

            // Create opening balance transaction if amount > 0
            if ($validated['opening_balance'] > 0) {
                SavingsTransaction::create([
                    'savings_account_id' => $account->id,
                    'transaction_number' => $this->generateTransactionNumber(),
                    'type' => 'deposit',
                    'amount' => $validated['opening_balance'],
                    'balance_before' => 0,
                    'balance_after' => $validated['opening_balance'],
                    'description' => 'Opening balance',
                    'transaction_date' => $validated['opening_date'],
                    'payment_method' => 'cash',
                    'created_by' => Auth::id(),
                ]);
            }

            DB::commit();
            Log::info('Savings account created successfully', [
                'account_id' => $account->id,
                'account_number' => $accountNumber,
                'client_id' => $account->client_id,
            ]);

            return redirect()->route('savings.accounts.show', $account)
                ->with('success', "Savings account created successfully! Account Number: {$accountNumber}");

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Failed to create savings account', [
                'error' => $e->getMessage(),
                'client_id' => $validated['client_id'] ?? null,
            ]);

            return back()->withInput()
                ->with('error', 'Failed to create savings account: ' . $e->getMessage());
        }
    }

    /**
     * Display the specified savings account details
     */
    public function show(SavingsAccount $savingsAccount)
    {
        $savingsAccount->load(['client', 'creator', 'transactions' => fn($q) => $q->latest()->limit(50)]);

        $stats = [
            'total_deposits' => $savingsAccount->transactions()->where('type', 'deposit')->sum('amount'),
            'total_withdrawals' => $savingsAccount->transactions()->where('type', 'withdrawal')->sum('amount'),
            'available_balance' => $savingsAccount->current_balance,
            'interest_earned' => $savingsAccount->transactions()->where('type', 'interest')->sum('amount'),
        ];

        return view('savings.accounts.show', compact('savingsAccount', 'stats'));
    }

    /**
     * Process a deposit into the savings account
     */
    public function deposit(Request $request, SavingsAccount $savingsAccount)
    {
        $validated = $request->validate([
            'amount' => 'required|numeric|min:0.01',
            'payment_method' => 'required|in:cash,mobile,bank,cheque',
            'reference_number' => 'nullable|string|max:255',
            'description' => 'nullable|string|max:255',
            'transaction_date' => 'required|date|before_or_equal:today',
        ]);

        try {
            DB::beginTransaction();

            $transaction = SavingsTransaction::create([
                'savings_account_id' => $savingsAccount->id,
                'transaction_number' => $this->generateTransactionNumber(),
                'type' => 'deposit',
                'amount' => $validated['amount'],
                'balance_before' => $savingsAccount->current_balance,
                'balance_after' => $savingsAccount->current_balance + $validated['amount'],
                'description' => $validated['description'] ?? 'Cash deposit',
                'transaction_date' => $validated['transaction_date'],
                'payment_method' => $validated['payment_method'],
                'reference_number' => $validated['reference_number'],
                'created_by' => Auth::id(),
            ]);

            $savingsAccount->increment('current_balance', $validated['amount']);

            // Auto-create cash book entry (permanent)
            CashTransaction::create([
                'transaction_code' => 'CB-' . date('Ymd') . '-' . strtoupper(Str::random(6)),
                'transaction_date' => $validated['transaction_date'],
                'transaction_type' => 'deposit',
                'cash_account_id' => 1,
                'amount' => $validated['amount'],
                'currency' => 'USD',
                'exchange_rate' => 1.0,
                'description' => "Savings deposit - {$savingsAccount->account_number} (" . ucfirst($validated['payment_method']) . ')',
                'reference_type' => 'savings_transaction',
                'reference_id' => $transaction->id,
                'status' => 'completed',
                'recorded_by' => Auth::id(),
            ]);

            // Auto-create journal entry (permanent)
            $journalEntry = JournalEntry::create([
                'entry_number' => 'JE-' . date('Ymd') . '-' . strtoupper(Str::random(6)),
                'entry_date' => $validated['transaction_date'],
                'description' => "Savings deposit - {$savingsAccount->account_number}",
                'reference_type' => 'savings_transaction',
                'reference_id' => $transaction->id,
                'status' => 'posted',
                'created_by' => Auth::id(),
            ]);

            // Journal entry items - Debit cash, Credit savings
            JournalEntryItem::insert([
                ['journal_entry_id' => $journalEntry->id, 'account_id' => 1, 'debit' => $validated['amount'], 'credit' => 0, 'description' => 'Cash received for savings deposit'],
                ['journal_entry_id' => $journalEntry->id, 'account_id' => 2, 'debit' => 0, 'credit' => $validated['amount'], 'description' => 'Savings deposit credited to account'],
            ]);

            // Auto-create receipt
            $receipt = Receipt::create([
                'client_id' => $savingsAccount->client_id,
                'receipt_date' => $validated['transaction_date'],
                'payment_method' => $validated['payment_method'],
                'amount' => $validated['amount'],
                'currency' => 'USD',
                'exchange_rate' => 1.0,
                'reference_type' => 'deposit',
                'reference_id' => $transaction->id,
                'collected_by' => Auth::id(),
                'status' => 'completed',
                'notes' => $validated['description'] ?? 'Savings deposit',
                'reference_number' => $validated['reference_number'],
            ]);

            // ========== ADD TEMP TABLE ENTRIES FOR CASHBOOK ==========
            CashbookTempEntry::create([
                'cashbook_id' => 1, // Default cashbook ID - adjust as needed
                'date' => $validated['transaction_date'],
                'module' => 'GL',
                'account_id' => 1, // Cash account ID
                'account_type' => GeneralLedger::class,
                'reference_id' => $transaction->id,
                'reference_type' => 'savings_transaction',
                'description' => "Savings deposit - {$savingsAccount->account_number}",
                'tr_code' => 'Receipt',
                'currency_id' => 1, // USD currency ID - adjust as needed
                'project_id' => null,
                'amount' => $validated['amount'],
                'dr_amount' => $validated['amount'],
                'cr_amount' => 0,
                'status' => 'Pending'
            ]);

            // ========== ADD TEMP TABLE ENTRIES FOR GENERAL JOURNAL ==========
            // Debit entry (Cash)
            GeneralJournalTemp::create([
                'date' => $validated['transaction_date'],
                'account_id' => 1, // Cash account ID
                'narration' => "Savings deposit - {$savingsAccount->account_number}",
                'reference' => $transaction->transaction_number,
                'currency_id' => 1, // USD currency ID
                'project_id' => null,
                'tr_code' => 'DR',
                'amount' => $validated['amount'],
                'status' => 'Pending'
            ]);

            // Credit entry (Savings Liability)
            GeneralJournalTemp::create([
                'date' => $validated['transaction_date'],
                'account_id' => 2, // Savings liability account ID
                'narration' => "Savings deposit - {$savingsAccount->account_number}",
                'reference' => $transaction->transaction_number,
                'currency_id' => 1, // USD currency ID
                'project_id' => null,
                'tr_code' => 'CR',
                'amount' => $validated['amount'],
                'status' => 'Pending'
            ]);

            DB::commit();
            Log::info('Savings deposit processed', [
                'account_id' => $savingsAccount->id,
                'transaction_id' => $transaction->id,
                'receipt_id' => $receipt->id,
                'amount' => $validated['amount']
            ]);

            return back()->with('success', "Deposit of USD " . number_format($validated['amount'], 2) . " processed successfully. Receipt: {$receipt->receipt_number}");

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Error processing savings deposit', ['account_id' => $savingsAccount->id, 'error' => $e->getMessage()]);
            return back()->with('error', 'Failed to process deposit: ' . $e->getMessage());
        }
    }

    /**
     * Process a withdrawal from the savings account
     */
    public function withdraw(Request $request, SavingsAccount $savingsAccount)
    {
        $validated = $request->validate([
            'amount' => 'required|numeric|min:0.01|max:' . ($savingsAccount->current_balance - $savingsAccount->minimum_balance),
            'payment_method' => 'required|in:cash,mobile,bank,cheque',
            'reference_number' => 'nullable|string|max:255',
            'description' => 'nullable|string|max:255',
            'transaction_date' => 'required|date|before_or_equal:today',
        ]);

        try {
            DB::beginTransaction();

            if (($savingsAccount->current_balance - $validated['amount']) < $savingsAccount->minimum_balance) {
                throw new \Exception('Withdrawal would violate minimum balance requirement.');
            }

            $transaction = SavingsTransaction::create([
                'savings_account_id' => $savingsAccount->id,
                'transaction_number' => $this->generateTransactionNumber(),
                'type' => 'withdrawal',
                'amount' => $validated['amount'],
                'balance_before' => $savingsAccount->current_balance,
                'balance_after' => $savingsAccount->current_balance - $validated['amount'],
                'description' => $validated['description'] ?? 'Cash withdrawal',
                'transaction_date' => $validated['transaction_date'],
                'payment_method' => $validated['payment_method'],
                'reference_number' => $validated['reference_number'],
                'created_by' => Auth::id(),
            ]);

            $savingsAccount->decrement('current_balance', $validated['amount']);

            // Auto-create cash book entry (permanent)
            CashTransaction::create([
                'transaction_code' => 'CB-' . date('Ymd') . '-' . strtoupper(Str::random(6)),
                'transaction_date' => $validated['transaction_date'],
                'transaction_type' => 'withdrawal',
                'cash_account_id' => 1,
                'amount' => $validated['amount'],
                'currency' => 'USD',
                'exchange_rate' => 1.0,
                'description' => "Savings withdrawal - {$savingsAccount->account_number} (" . ucfirst($validated['payment_method']) . ')',
                'reference_type' => 'savings_transaction',
                'reference_id' => $transaction->id,
                'status' => 'completed',
                'recorded_by' => Auth::id(),
            ]);

            // Auto-create journal entry (permanent)
            $journalEntry = JournalEntry::create([
                'entry_number' => 'JE-' . date('Ymd') . '-' . strtoupper(Str::random(6)),
                'entry_date' => $validated['transaction_date'],
                'description' => "Savings withdrawal - {$savingsAccount->account_number}",
                'reference_type' => 'savings_transaction',
                'reference_id' => $transaction->id,
                'status' => 'posted',
                'created_by' => Auth::id(),
            ]);

            // Journal entry items - Debit savings, Credit cash
            JournalEntryItem::insert([
                ['journal_entry_id' => $journalEntry->id, 'account_id' => 2, 'debit' => $validated['amount'], 'credit' => 0, 'description' => 'Savings withdrawal debited from account'],
                ['journal_entry_id' => $journalEntry->id, 'account_id' => 1, 'debit' => 0, 'credit' => $validated['amount'], 'description' => 'Cash paid for savings withdrawal'],
            ]);

            // Auto-create receipt (as payment voucher)
            $receipt = Receipt::create([
                'client_id' => $savingsAccount->client_id,
                'receipt_date' => $validated['transaction_date'],
                'payment_method' => $validated['payment_method'],
                'amount' => $validated['amount'],
                'currency' => 'USD',
                'exchange_rate' => 1.0,
                'reference_type' => 'withdrawal',
                'reference_id' => $transaction->id,
                'collected_by' => Auth::id(),
                'status' => 'completed',
                'notes' => $validated['description'] ?? 'Savings withdrawal',
                'reference_number' => $validated['reference_number'],
            ]);

            // ========== ADD TEMP TABLE ENTRIES FOR CASHBOOK ==========
            CashbookTempEntry::create([
                'cashbook_id' => 1, // Default cashbook ID - adjust as needed
                'date' => $validated['transaction_date'],
                'module' => 'GL',
                'account_id' => 1, // Cash account ID
                'account_type' => GeneralLedger::class,
                'reference_id' => $transaction->id,
                'reference_type' => 'savings_transaction',
                'description' => "Savings withdrawal - {$savingsAccount->account_number}",
                'tr_code' => 'Payment',
                'currency_id' => 1, // USD currency ID - adjust as needed
                'project_id' => null,
                'amount' => $validated['amount'],
                'dr_amount' => 0,
                'cr_amount' => $validated['amount'],
                'status' => 'Pending'
            ]);

            // ========== ADD TEMP TABLE ENTRIES FOR GENERAL JOURNAL ==========
            // Debit entry (Savings Liability)
            GeneralJournalTemp::create([
                'date' => $validated['transaction_date'],
                'account_id' => 2, // Savings liability account ID
                'narration' => "Savings withdrawal - {$savingsAccount->account_number}",
                'reference' => $transaction->transaction_number,
                'currency_id' => 1, // USD currency ID
                'project_id' => null,
                'tr_code' => 'DR',
                'amount' => $validated['amount'],
                'status' => 'Pending'
            ]);

            // Credit entry (Cash)
            GeneralJournalTemp::create([
                'date' => $validated['transaction_date'],
                'account_id' => 1, // Cash account ID
                'narration' => "Savings withdrawal - {$savingsAccount->account_number}",
                'reference' => $transaction->transaction_number,
                'currency_id' => 1, // USD currency ID
                'project_id' => null,
                'tr_code' => 'CR',
                'amount' => $validated['amount'],
                'status' => 'Pending'
            ]);

            DB::commit();
            Log::info('Savings withdrawal processed', [
                'account_id' => $savingsAccount->id,
                'transaction_id' => $transaction->id,
                'receipt_id' => $receipt->id,
                'amount' => $validated['amount']
            ]);

            return back()->with('success', "Withdrawal of USD " . number_format($validated['amount'], 2) . " processed successfully. Receipt: {$receipt->receipt_number}");

        } catch (\Exception $e) {
            DB::rollBack();
            Log::error('Error processing savings withdrawal', ['account_id' => $savingsAccount->id, 'error' => $e->getMessage()]);
            return back()->with('error', 'Failed to process withdrawal: ' . $e->getMessage());
        }
    }

    /**
     * Display a listing of savings transactions
     */
    public function transactions(Request $request)
    {
        $query = SavingsTransaction::with(['savingsAccount.client', 'creator']);

        $query->when($request->type, fn($q) => $q->where('type', $request->type))
              ->when($request->from_date, fn($q) => $q->whereDate('transaction_date', '>=', $request->from_date))
              ->when($request->to_date, fn($q) => $q->whereDate('transaction_date', '<=', $request->to_date))
              ->when($request->search, function($q) use ($request) {
                  $q->where('transaction_number', 'like', "%{$request->search}%")
                    ->orWhereHas('savingsAccount.client', fn($q) => $q->where('first_name', 'like', "%{$request->search}%")
                        ->orWhere('last_name', 'like', "%{$request->search}%"));
              });

        $transactions = $query->latest('transaction_date')->paginate(50);
        return view('savings.transactions', compact('transactions'));
    }

    /**
     * Update the specified savings account
     */
    public function update(Request $request, SavingsAccount $savingsAccount)
    {
        $validated = $request->validate([
            'product_name' => 'required|string|max:255',
            'minimum_balance' => 'required|numeric|min:0',
            'interest_rate' => 'required|numeric|min:0|max:100',
            'interest_calculation' => 'required|in:daily,monthly,quarterly,annually',
            'maturity_date' => 'nullable|date|after:opening_date',
            'status' => 'required|in:active,dormant,closed,frozen',
            'notes' => 'nullable|string',
        ]);

        try {
            $savingsAccount->update($validated);
            return redirect()->route('savings.accounts.show', $savingsAccount)
                ->with('success', 'Savings account updated successfully.');
        } catch (\Exception $e) {
            return back()->withInput()->with('error', 'Failed to update savings account: ' . $e->getMessage());
        }
    }

    /**
     * Close the specified savings account
     */
    public function destroy(SavingsAccount $savingsAccount)
    {
        try {
            if ($savingsAccount->current_balance > 0) {
                return back()->with('error', 'Cannot close account with balance. Please withdraw all funds first.');
            }

            $savingsAccount->update(['status' => 'closed']);
            Log::info('Savings account closed', ['account_id' => $savingsAccount->id, 'account_number' => $savingsAccount->account_number]);

            return redirect()->route('savings.accounts.index')->with('success', 'Savings account closed successfully.');

        } catch (\Exception $e) {
            Log::error('Error closing savings account', ['account_id' => $savingsAccount->id, 'error' => $e->getMessage()]);
            return back()->with('error', 'Failed to close savings account: ' . $e->getMessage());
        }
    }

    private function generateAccountNumber()
    {
        do {
            $number = 'SA' . date('Ymd') . strtoupper(Str::random(6));
        } while (SavingsAccount::where('account_number', $number)->exists());

        return $number;
    }

    private function generateTransactionNumber()
    {
        do {
            $number = 'TXN' . date('YmdHis') . strtoupper(Str::random(4));
        } while (SavingsTransaction::where('transaction_number', $number)->exists());

        return $number;
    }

    /**
     * Display a listing of savings deposits
     */
    public function deposits(Request $request)
    {
        $query = SavingsTransaction::with(['savingsAccount.client', 'creator'])->where('type', 'deposit');

        $query->when($request->from_date, fn($q) => $q->whereDate('transaction_date', '>=', $request->from_date))
              ->when($request->to_date, fn($q) => $q->whereDate('transaction_date', '<=', $request->to_date))
              ->when($request->search, function($q) use ($request) {
                  $q->where('transaction_number', 'like', "%{$request->search}%")
                    ->orWhereHas('savingsAccount.client', fn($q) => $q->where('first_name', 'like', "%{$request->search}%")
                        ->orWhere('last_name', 'like', "%{$request->search}%"));
              });

        $deposits = $query->latest('transaction_date')->paginate(50);
        return view('savings.deposits', compact('deposits'));
    }

    public function withdrawals(Request $request)
    {
        $query = SavingsTransaction::with(['savingsAccount.client', 'creator'])
            ->where('type', 'withdrawal');

        if ($request->filled('from_date')) {
            $query->whereDate('transaction_date', '>=', $request->from_date);
        }
        if ($request->filled('to_date')) {
            $query->whereDate('transaction_date', '<=', $request->to_date);
        }

        if ($request->filled('search')) {
            $query->where(function($q) use ($request) {
                $q->where('transaction_number', 'like', '%' . $request->search . '%')
                  ->orWhereHas('savingsAccount.client', function($q) use ($request) {
                      $q->where('first_name', 'like', '%' . $request->search . '%')
                        ->orWhere('last_name', 'like', '%' . $request->search . '%');
                  });
            });
        }

        $withdrawals = $query->latest('transaction_date')->paginate(50);

        return view('savings.withdrawals', compact('withdrawals'));
    }

    public function interest()
    {
        $accounts = SavingsAccount::with('client')
            ->where('status', 'active')
            ->where('type', '!=', 'current')
            ->get();

        return view('savings.interest', compact('accounts'));
    }

    /**
     * Link a loan to the savings account
     */
    public function linkToLoan(Request $request, SavingsAccount $savingsAccount)
    {
        $validated = $request->validate(['loan_id' => 'required|integer|exists:loans,id']);
        $loan = Loan::findOrFail($validated['loan_id']);

        if ($loan->client_id !== $savingsAccount->client_id) {
            return back()->with('error', 'Loan and savings account must belong to the same client.');
        }

        if ($loan->savings_account_id) {
            return back()->with('error', 'This loan is already linked to a savings account.');
        }

        try {
            $loan->update(['savings_account_id' => $savingsAccount->id]);
            Log::info('Loan linked to savings account', ['loan_id' => $loan->id, 'savings_account_id' => $savingsAccount->id]);
            return back()->with('success', 'Loan successfully linked to savings account.');
        } catch (\Exception $e) {
            Log::error('Error linking loan to savings account', ['loan_id' => $loan->id, 'savings_account_id' => $savingsAccount->id, 'error' => $e->getMessage()]);
            return back()->with('error', 'Error linking loan to savings account.');
        }
    }

    /**
     * Unlink a loan from the savings account
     */
    public function unlinkFromLoan(SavingsAccount $savingsAccount, Loan $loan)
    {
        if ($loan->savings_account_id !== $savingsAccount->id) {
            return back()->with('error', 'Loan is not linked to this savings account.');
        }

        try {
            $loan->update(['savings_account_id' => null]);
            Log::info('Loan unlinked from savings account', ['loan_id' => $loan->id, 'savings_account_id' => $savingsAccount->id]);
            return back()->with('success', 'Loan successfully unlinked from savings account.');
        } catch (\Exception $e) {
            Log::error('Error unlinking loan from savings account', ['loan_id' => $loan->id, 'savings_account_id' => $savingsAccount->id, 'error' => $e->getMessage()]);
            return back()->with('error', 'Error unlinking loan from savings account.');
        }
    }

    /**
     * Get available loans for linking to savings account
     */
    public function getAvailableLoans(SavingsAccount $savingsAccount)
    {
        $loans = Loan::where('client_id', $savingsAccount->client_id)->whereNull('savings_account_id')->whereIn('status', ['pending', 'approved', 'disbursed'])->with('loanProduct')->get();
        return response()->json($loans);
    }

    /**
     * Show the form for editing the specified savings account
     */
    public function edit(SavingsAccount $savingsAccount)
    {
        $clients = Client::where('status', 'active')->orderBy('first_name')->get();
        $products = $this->getSavingsProducts();

        return view('savings.accounts.edit', compact('savingsAccount', 'clients', 'products'));
    }

    /**
     * Show deposit form
     */
    public function showDepositForm()
    {
        return view('savings.deposits-create');
    }

    /**
     * Show withdrawal form
     */
    public function showWithdrawForm()
    {
        return view('savings.withdrawal-create');
    }

    /**
     * Show the edit/delete form for savings accounts
     */
    public function editDelete(Request $request)
    {
        $query = SavingsAccount::with(['client', 'creator']);

        $query->when($request->account_number, fn($q) => $q->where('account_number', 'like', "%{$request->account_number}%"))
              ->when($request->client_name, function($q) use ($request) {
                  $q->whereHas('client', fn($q) => $q->where('first_name', 'like', "%{$request->client_name}%")
                      ->orWhere('last_name', 'like', "%{$request->client_name}%"));
              })
              ->when($request->status, fn($q) => $q->where('status', $request->status));

        $savingsAccounts = $query->paginate(20);
        return view('savings.accounts.edit-delete', compact('savingsAccounts'));
    }

    public function printAll(Request $request)
    {
        $query = SavingsAccount::with(['client', 'creator', 'loans']);

        if ($request->filled('search')) {
            $query->where(function($q) use ($request) {
                $q->where('account_number', 'like', '%' . $request->search . '%')
                  ->orWhereHas('client', function($q) use ($request) {
                      $q->where('first_name', 'like', '%' . $request->search . '%')
                        ->orWhere('last_name', 'like', '%' . $request->search . '%')
                        ->orWhere('client_number', 'like', '%' . $request->search . '%');
                  });
            });
        }

        if ($request->filled('status')) {
            $query->where('status', $request->status);
        }

        if ($request->filled('type')) {
            $query->where('type', $request->type);
        }

        if ($request->filled('has_loans')) {
            if ($request->has_loans === 'yes') {
                $query->has('loans');
            } elseif ($request->has_loans === 'no') {
                $query->doesntHave('loans');
            }
        }

        // Month filter
        if ($request->filled('month') && $request->filled('year')) {
            $query->whereMonth('created_at', $request->month)
                  ->whereYear('created_at', $request->year);
        }

        // Category filter (account type)
        if ($request->filled('category')) {
            $query->where('type', $request->category);
        }

        $savingsAccounts = $query->get();

        return view('savings.accounts.print-all', compact('savingsAccounts'));
    }

    /**
     * Print single savings account details
     */
    public function printSingle(SavingsAccount $savingsAccount)
    {
        $savingsAccount->load(['client', 'creator', 'transactions' => fn($q) => $q->latest()->limit(50)]);

        $stats = [
            'total_deposits' => $savingsAccount->transactions()->where('type', 'deposit')->sum('amount'),
            'total_withdrawals' => $savingsAccount->transactions()->where('type', 'withdrawal')->sum('amount'),
            'available_balance' => $savingsAccount->current_balance,
            'interest_earned' => $savingsAccount->transactions()->where('type', 'interest')->sum('amount'),
        ];

        return view('savings.accounts.print-single', compact('savingsAccount', 'stats'));
    }

    /**
     * Download all savings accounts as PDF
     */
    public function downloadAll(Request $request)
    {
        $query = SavingsAccount::with(['client', 'creator', 'loans']);

        $query->when($request->search, function($q) use ($request) {
                $q->where('account_number', 'like', "%{$request->search}%")
                  ->orWhereHas('client', fn($q) => $q->where('first_name', 'like', "%{$request->search}%")
                      ->orWhere('last_name', 'like', "%{$request->search}%")
                      ->orWhere('client_number', 'like', "%{$request->search}%"));
              })
              ->when($request->status, fn($q) => $q->where('status', $request->status))
              ->when($request->type, fn($q) => $q->where('type', $request->type))
              ->when($request->has_loans === 'yes', fn($q) => $q->has('loans'))
              ->when($request->has_loans === 'no', fn($q) => $q->doesntHave('loans'))
              ->when($request->filled('month') && $request->filled('year'), fn($q) => $q->whereMonth('created_at', $request->month)->whereYear('created_at', $request->year))
              ->when($request->category, fn($q) => $q->where('type', $request->category));

        $savingsAccounts = $query->get();
        $pdf = PDF::loadView('savings.accounts.print-all', compact('savingsAccounts'));
        $filename = 'savings-accounts-report-' . now()->format('Y-m-d-H-i-s') . '.pdf';

        return $pdf->download($filename);
    }

    public function downloadSingle(SavingsAccount $savingsAccount)
    {
        $savingsAccount->load(['client', 'creator', 'transactions' => function($query) {
            $query->latest()->limit(50);
        }]);

        $totalDeposits = $savingsAccount->transactions()
            ->where('type', 'deposit')
            ->sum('amount');

        $totalWithdrawals = $savingsAccount->transactions()
            ->where('type', 'withdrawal')
            ->sum('amount');

        $stats = [
            'total_deposits' => $totalDeposits,
            'total_withdrawals' => $totalWithdrawals,
            'available_balance' => $savingsAccount->current_balance,
            'interest_earned' => $savingsAccount->transactions()
                ->where('type', 'interest')
                ->sum('amount'),
        ];

        $pdf = Pdf::loadView('savings.accounts.print-single', compact('savingsAccount', 'stats'));
        $filename = 'savings-account-' . $savingsAccount->account_number . '-' . now()->format('Y-m-d') . '.pdf';

        return $pdf->download($filename);
    }

    /**
     * Print savings deposits report
     */
    public function printDeposits(Request $request)
    {
        $query = SavingsTransaction::with(['savingsAccount.client', 'creator'])->where('type', 'deposit');

        $query->when($request->from_date, fn($q) => $q->whereDate('transaction_date', '>=', $request->from_date))
              ->when($request->to_date, fn($q) => $q->whereDate('transaction_date', '<=', $request->to_date))
              ->when($request->search, function($q) use ($request) {
                  $q->where('transaction_number', 'like', "%{$request->search}%")
                    ->orWhereHas('savingsAccount.client', fn($q) => $q->where('first_name', 'like', "%{$request->search}%")
                        ->orWhere('last_name', 'like', "%{$request->search}%"));
              })
              ->when($request->filled('month') && $request->filled('year'), fn($q) => $q->whereMonth('transaction_date', $request->month)->whereYear('transaction_date', $request->year))
              ->when($request->category, fn($q) => $q->where('payment_method', $request->category));

        $deposits = $query->get();
        return view('savings.deposits-print', compact('deposits'));
    }

    /**
     * Download savings deposits report as PDF
     */
    public function downloadDeposits(Request $request)
    {
        $query = SavingsTransaction::with(['savingsAccount.client', 'creator'])->where('type', 'deposit');

        $query->when($request->from_date, fn($q) => $q->whereDate('transaction_date', '>=', $request->from_date))
              ->when($request->to_date, fn($q) => $q->whereDate('transaction_date', '<=', $request->to_date))
              ->when($request->search, function($q) use ($request) {
                  $q->where('transaction_number', 'like', "%{$request->search}%")
                    ->orWhereHas('savingsAccount.client', fn($q) => $q->where('first_name', 'like', "%{$request->search}%")
                        ->orWhere('last_name', 'like', "%{$request->search}%"));
              })
              ->when($request->filled('month') && $request->filled('year'), fn($q) => $q->whereMonth('transaction_date', $request->month)->whereYear('transaction_date', $request->year))
              ->when($request->category, fn($q) => $q->where('payment_method', $request->category));

        $deposits = $query->get();
        $pdf = PDF::loadView('savings.deposits-print', compact('deposits'));
        $filename = 'savings-deposits-report-' . now()->format('Y-m-d-H-i-s') . '.pdf';

        return $pdf->download($filename);
    }

    /**
     * Print savings withdrawals report
     */
    public function printWithdrawals(Request $request)
    {
        $query = SavingsTransaction::with(['savingsAccount.client', 'creator'])->where('type', 'withdrawal');

        $query->when($request->from_date, fn($q) => $q->whereDate('transaction_date', '>=', $request->from_date))
              ->when($request->to_date, fn($q) => $q->whereDate('transaction_date', '<=', $request->to_date))
              ->when($request->search, function($q) use ($request) {
                  $q->where('transaction_number', 'like', "%{$request->search}%")
                    ->orWhereHas('savingsAccount.client', fn($q) => $q->where('first_name', 'like', "%{$request->search}%")
                        ->orWhere('last_name', 'like', "%{$request->search}%"));
              })
              ->when($request->filled('month') && $request->filled('year'), fn($q) => $q->whereMonth('transaction_date', $request->month)->whereYear('transaction_date', $request->year))
              ->when($request->category, fn($q) => $q->where('payment_method', $request->category));

        $withdrawals = $query->get();
        return view('savings.withdrawals-print', compact('withdrawals'));
    }

    public function downloadWithdrawals(Request $request)
    {
        $query = SavingsTransaction::with(['savingsAccount.client', 'creator'])
            ->where('type', 'withdrawal');

        if ($request->filled('from_date')) {
            $query->whereDate('transaction_date', '>=', $request->from_date);
        }
        if ($request->filled('to_date')) {
            $query->whereDate('transaction_date', '<=', $request->to_date);
        }

        if ($request->filled('search')) {
            $query->where(function($q) use ($request) {
                $q->where('transaction_number', 'like', '%' . $request->search . '%')
                  ->orWhereHas('savingsAccount.client', function($q) use ($request) {
                      $q->where('first_name', 'like', '%' . $request->search . '%')
                        ->orWhere('last_name', 'like', '%' . $request->search . '%');
                  });
            });
        }

        // Month filter
        if ($request->filled('month') && $request->filled('year')) {
            $query->whereMonth('transaction_date', $request->month)
                  ->whereYear('transaction_date', $request->year);
        }

        // Category filter (payment method)
        if ($request->filled('category')) {
            $query->where('payment_method', $request->category);
        }

        $withdrawals = $query->get();

        $pdf = Pdf::loadView('savings.withdrawals-print', compact('withdrawals'));
        $filename = 'savings-withdrawals-report-' . now()->format('Y-m-d-H-i-s') . '.pdf';

        return $pdf->download($filename);
    }

    public function printSingleDeposit(SavingsTransaction $deposit)
    {
        if ($deposit->type !== 'deposit') {
            abort(404);
        }

        $deposit->load(['savingsAccount.client', 'creator']);

        return view('savings.deposits-print-single', compact('deposit'));
    }

    /**
     * Download single deposit receipt as PDF
     */
    public function downloadSingleDeposit(SavingsTransaction $deposit)
    {
        abort_unless($deposit->type === 'deposit', 404);
        $deposit->load(['savingsAccount.client', 'creator']);

        $pdf = Pdf::loadView('savings.deposits-print-single', compact('deposit'));
        $filename = "savings-deposit-{$deposit->transaction_number}-" . now()->format('Y-m-d') . '.pdf';

        return $pdf->download($filename);
    }

    /**
     * Print single withdrawal receipt
     */
    public function printSingleWithdrawal(SavingsTransaction $withdrawal)
    {
        abort_unless($withdrawal->type === 'withdrawal', 404);
        $withdrawal->load(['savingsAccount.client', 'creator']);

        return view('savings.withdrawals-print-single', compact('withdrawal'));
    }

    public function downloadSingleWithdrawal(SavingsTransaction $withdrawal)
    {
        if ($withdrawal->type !== 'withdrawal') {
            abort(404);
        }

        $withdrawal->load(['savingsAccount.client', 'creator']);

        $pdf = Pdf::loadView('savings.withdrawals-print-single', compact('withdrawal'));
        $filename = 'savings-withdrawal-' . $withdrawal->transaction_number . '-' . now()->format('Y-m-d') . '.pdf';

        return $pdf->download($filename);
    }
}
