<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use App\Models\BankAccount;
use App\Models\PettyCashTransaction;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\View\View;

class PettyCashController extends Controller
{
    public function index(): View
    {
        $transactions = PettyCashTransaction::with(['creator', 'bankAccount', 'returnedFrom'])
            ->orderBy('transaction_date', 'desc')
            ->orderBy('created_at', 'desc')
            ->get();

        // Calculate stats
        $totalPettyCash = PettyCashTransaction::where('type', 'top_up')
            ->where('status', 'approved')
            ->sum('amount');

        $totalDisbursed = PettyCashTransaction::where('type', 'disbursement')
            ->where('status', 'approved')
            ->sum('amount');

        $totalReturned = PettyCashTransaction::where('type', 'return')
            ->where('status', 'approved')
            ->sum('returned_amount');

        $balance = $totalPettyCash - $totalDisbursed + $totalReturned;

        // Get pending transactions for return dropdown
        $pendingTransactions = PettyCashTransaction::where('type', 'disbursement')
            ->where('status', 'approved')
            ->whereDoesntHave('returns', function ($query) {
                $query->where('status', 'approved');
            })
            ->get();

        // Get bank accounts for top-up
        $bankAccounts = BankAccount::where('is_active', true)
            ->orderBy('is_default', 'desc')
            ->orderBy('account_name')
            ->get();

        return view('admin.petty-cash.index', [
            'transactions' => $transactions,
            'totalPettyCash' => $totalPettyCash,
            'totalDisbursed' => $totalDisbursed,
            'balance' => $balance,
            'pendingTransactions' => $pendingTransactions,
            'bankAccounts' => $bankAccounts,
        ]);
    }

    public function store(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'amount' => 'required|numeric|min:0.01',
            'given_to' => 'required|string|max:255',
            'description' => 'required|string',
            'date' => 'required|date',
            'notes' => 'nullable|string',
        ]);

        try {
            DB::beginTransaction();

            $transaction = PettyCashTransaction::create([
                'transaction_number' => PettyCashTransaction::generateTransactionNumber(),
                'transaction_date' => $validated['date'],
                'type' => 'disbursement',
                'amount' => $validated['amount'],
                'given_to' => $validated['given_to'],
                'description' => $validated['description'],
                'notes' => $validated['notes'] ?? null,
                'status' => 'approved',
                'created_by' => Auth::id(),
                'approved_by' => Auth::id(),
                'approved_at' => now(),
            ]);

            DB::commit();

            return redirect()->route('admin.petty-cash.index')
                ->with('success', 'Petty cash disbursement added successfully.');
        } catch (\Exception $e) {
            DB::rollBack();

            return redirect()->route('admin.petty-cash.index')
                ->with('error', 'Failed to add petty cash: '.$e->getMessage());
        }
    }

    public function update(Request $request, $id): RedirectResponse
    {
        $transaction = PettyCashTransaction::findOrFail($id);

        if ($transaction->type === 'return' && $transaction->status === 'approved') {
            return redirect()->route('admin.petty-cash.index')
                ->with('error', 'Cannot edit approved return transactions.');
        }

        $validated = $request->validate([
            'amount' => 'required|numeric|min:0.01',
            'given_to' => 'required|string|max:255',
            'description' => 'required|string',
            'date' => 'required|date',
            'notes' => 'nullable|string',
        ]);

        try {
            DB::beginTransaction();

            $transaction->update([
                'transaction_date' => $validated['date'],
                'amount' => $validated['amount'],
                'given_to' => $validated['given_to'],
                'description' => $validated['description'],
                'notes' => $validated['notes'] ?? null,
            ]);

            DB::commit();

            return redirect()->route('admin.petty-cash.index')
                ->with('success', 'Petty cash transaction updated successfully.');
        } catch (\Exception $e) {
            DB::rollBack();

            return redirect()->route('admin.petty-cash.index')
                ->with('error', 'Failed to update transaction: '.$e->getMessage());
        }
    }

    public function destroy($id): RedirectResponse
    {
        $transaction = PettyCashTransaction::findOrFail($id);

        if ($transaction->status === 'approved' && $transaction->returns()->count() > 0) {
            return redirect()->route('admin.petty-cash.index')
                ->with('error', 'Cannot delete transaction with returns. Please delete returns first.');
        }

        try {
            $transaction->delete();

            return redirect()->route('admin.petty-cash.index')
                ->with('success', 'Petty cash transaction deleted successfully.');
        } catch (\Exception $e) {
            return redirect()->route('admin.petty-cash.index')
                ->with('error', 'Failed to delete transaction: '.$e->getMessage());
        }
    }

    public function return(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'transaction_id' => 'required|exists:petty_cash_transactions,id',
            'return_amount' => 'required|numeric|min:0.01',
            'notes' => 'nullable|string',
        ]);

        $originalTransaction = PettyCashTransaction::findOrFail($validated['transaction_id']);

        $alreadyReturned = $originalTransaction->returns()
            ->where('status', 'approved')
            ->sum('returned_amount');

        $maxReturnable = $originalTransaction->amount - $alreadyReturned;

        if ($validated['return_amount'] > $maxReturnable) {
            return redirect()->route('admin.petty-cash.index')
                ->with('error', 'Return amount cannot exceed the remaining balance of '.number_format($maxReturnable, 2));
        }

        try {
            DB::beginTransaction();

            $returnTransaction = PettyCashTransaction::create([
                'transaction_number' => PettyCashTransaction::generateTransactionNumber(),
                'transaction_date' => now()->toDateString(),
                'type' => 'return',
                'amount' => $validated['return_amount'],
                'given_to' => $originalTransaction->given_to,
                'description' => 'Return of petty cash: '.$originalTransaction->description,
                'notes' => $validated['notes'] ?? null,
                'status' => 'approved',
                'returned_from_id' => $originalTransaction->id,
                'returned_amount' => $validated['return_amount'],
                'created_by' => Auth::id(),
                'approved_by' => Auth::id(),
                'approved_at' => now(),
            ]);

            DB::commit();

            return redirect()->route('admin.petty-cash.index')
                ->with('success', 'Petty cash returned successfully.');
        } catch (\Exception $e) {
            DB::rollBack();

            return redirect()->route('admin.petty-cash.index')
                ->with('error', 'Failed to return petty cash: '.$e->getMessage());
        }
    }

    public function topUp(Request $request): RedirectResponse
    {
        $validated = $request->validate([
            'amount' => 'required|numeric|min:0.01',
            'bank_account_id' => 'required|exists:bank_accounts,id',
            'description' => 'required|string',
            'date' => 'required|date',
            'notes' => 'nullable|string',
        ]);

        try {
            DB::beginTransaction();

            $transaction = PettyCashTransaction::create([
                'transaction_number' => PettyCashTransaction::generateTransactionNumber(),
                'transaction_date' => $validated['date'],
                'type' => 'top_up',
                'amount' => $validated['amount'],
                'description' => $validated['description'],
                'notes' => $validated['notes'] ?? null,
                'status' => 'approved',
                'bank_account_id' => $validated['bank_account_id'],
                'created_by' => Auth::id(),
                'approved_by' => Auth::id(),
                'approved_at' => now(),
            ]);

            DB::commit();

            return redirect()->route('admin.petty-cash.index')
                ->with('success', 'Petty cash top-up added successfully.');
        } catch (\Exception $e) {
            DB::rollBack();

            return redirect()->route('admin.petty-cash.index')
                ->with('error', 'Failed to add top-up: '.$e->getMessage());
        }
    }
}
