<?php

namespace App\Http\Controllers\Admin;

use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Models\Account;
use App\Models\JournalTransaction;
use App\Models\JournalEntry;
use App\Models\PettyCashExpense;
use App\Http\Controllers\Controller;
use Carbon\Carbon;


class PettyCashController extends Controller
{
    public function index()
    {
        // Get parent Petty Cash account
        $parent = Account::where('name', 'Petty Cash')
            ->whereNull('parent_id')
            ->firstOrFail();

        // Get all child petty cash accounts
        $accounts = Account::where('parent_id', $parent->id)
            ->where('type', 'asset')
            ->where('is_posting', 1)
            ->with('user')
            ->orderBy('name')
            ->get();

        return view('admin.pettycash.index', compact('parent', 'accounts'));
    }

    public function show(Account $account)
    {
        // Ensure this is a petty cash child account
        abort_if($account->parent_id === null, 404);

        $ledger = JournalTransaction::where('account_id', $account->id)
            ->with('journalEntry')
            ->orderBy('id')
            ->get();

        return view('admin.pettycash.show', compact('account', 'ledger'));
    }

    public function topupForm(Account $account)
    {
        abort_if($account->parent_id === null, 404);

        $sourceAccounts = Account::whereIn('code', [
            '1000',
            '1001',
            '1002',
            '1003',
            '1005'
        ])
            ->where('is_posting', 1)
            ->get()
            ->map(function ($acc) {
                $debit = JournalTransaction::where('account_id', $acc->id)->sum('debit');
                $credit = JournalTransaction::where('account_id', $acc->id)->sum('credit');

                $acc->balance = $debit - $credit;
                return $acc;
            });

        return view('admin.pettycash.topup', compact('account', 'sourceAccounts'));
    }

    public function topupStore(Request $request, Account $account)
    {
        abort_if($account->parent_id === null, 404);

        $request->validate([
            'source_account_id' => 'required|exists:accounts,id',
            'amount' => 'required|numeric|min:0.01',
            'date' => 'required|date',
            'description' => 'nullable|string',
        ]);

        $sourceAccount = Account::findOrFail($request->source_account_id);

        $availableBalance =
            JournalTransaction::where('account_id', $sourceAccount->id)->sum('debit')
            -
            JournalTransaction::where('account_id', $sourceAccount->id)->sum('credit');

        if ($request->amount > $availableBalance) {
            return back()
                ->withErrors(['amount' => 'Insufficient balance in source account'])
                ->withInput();
        }


        DB::transaction(function () use ($request, $account) {

            $journal = JournalEntry::create([
                'date' => $request->date,
                'reference' => 'PC-TOPUP-' . now()->timestamp,
                'description' => $request->description
                    ?? 'Petty cash top-up: ' . $account->name,

                'user_id' => auth()->id(),     // ✅ REQUIRED
                'created_by' => auth()->id(),  // (keep if you already use it)
            ]);


            // Debit Petty Cash
            JournalTransaction::create([
                'journal_entry_id' => $journal->id,
                'account_id' => $account->id,
                'debit' => $request->amount,
                'credit' => 0,
                'user_id' => auth()->id(),
            ]);

            // Credit Source Account
            JournalTransaction::create([
                'journal_entry_id' => $journal->id,
                'account_id' => $request->source_account_id,
                'debit' => 0,
                'credit' => $request->amount,
                'user_id' => auth()->id(),
            ]);
        });

        return redirect()
            ->route('admin.pettycash.show', $account->id)
            ->with('success', 'Petty cash topped up successfully.');
    }

    public function myLedger(Request $request)
    {
        $user = Auth::user();

        // Get parent Petty Cash account
        $parent = Account::where('name', 'Petty Cash')
            ->whereNull('parent_id')
            ->firstOrFail();

        // Get user's petty cash child account
        $account = Account::where('parent_id', $parent->id)
            ->where('user_id', $user->id)
            ->where('is_posting', 1)
            ->firstOrFail();

        // Selected month (default = current month)
        $selectedMonth = $request->get(
            'month',
            now()->format('Y-m')
        );

        $startDate = Carbon::createFromFormat('Y-m', $selectedMonth)->startOfMonth();
        $endDate   = Carbon::createFromFormat('Y-m', $selectedMonth)->endOfMonth();

        // Get transactions ONLY for selected month
        $transactions = JournalTransaction::where('account_id', $account->id)
            ->join('journal_entries', 'journal_entries.id', '=', 'journal_transactions.journal_entry_id')
            ->whereBetween('journal_entries.date', [$startDate, $endDate])
            ->orderBy('journal_entries.date')
            ->orderBy('journal_transactions.id')
            ->select('journal_transactions.*')
            ->with('journalEntry')
            ->get();

        // Build month dropdown (current + previous 6 months)
        $months = collect();
        for ($i = 0; $i <= 6; $i++) {
            $months->push(
                now()->subMonths($i)->format('Y-m')
            );
        }

        // Get pending expenses for this user
        $pendingExpenses = PettyCashExpense::where('user_id', $user->id)
            ->where('petty_cash_account_id', $account->id)
            ->where('status', 'pending')
            ->with(['expenseAccount'])
            ->orderBy('created_at', 'desc')
            ->get();

        // Get approved expenses for the selected month to show receipt images
        $approvedExpenses = PettyCashExpense::where('user_id', $user->id)
            ->where('petty_cash_account_id', $account->id)
            ->where('status', 'approved')
            ->whereBetween('expense_date', [$startDate, $endDate])
            ->with(['expenseAccount'])
            ->get()
            ->keyBy(function($expense) {
                // Create a unique key for matching: date_amount
                return $expense->expense_date->format('Y-m-d') . '_' . $expense->amount;
            });

        return view('admin.pettycash.my-ledger', compact(
            'account',
            'transactions',
            'months',
            'selectedMonth',
            'pendingExpenses',
            'approvedExpenses'
        ));
    }



    public function myExpenseForm()
    {
        $expenseAccounts = Account::where('type', 'expense')
            ->where('is_posting', 1)
            ->where('show_in_petty_cash', true)
            ->orderBy('name')
            ->get();

        return view('admin.pettycash.my-expense', compact('expenseAccounts'));
    }

    public function editMyExpense(PettyCashExpense $expense)
    {
        $user = Auth::user();

        // Ensure user can only edit their own expenses
        if ($expense->user_id !== $user->id) {
            abort(403, 'Unauthorized action.');
        }

        // Ensure expense is still pending
        if ($expense->status !== 'pending') {
            return redirect()
                ->route('admin.pettycash.my-ledger')
                ->withErrors(['error' => 'Cannot edit an expense that has already been processed.']);
        }

        $expenseAccounts = Account::where('type', 'expense')
            ->where('is_posting', 1)
            ->where('show_in_petty_cash', true)
            ->orderBy('name')
            ->get();

        return view('admin.pettycash.edit-my-expense', compact('expense', 'expenseAccounts'));
    }

    public function updateMyExpense(Request $request, PettyCashExpense $expense)
    {
        $user = Auth::user();

        // Ensure user can only update their own expenses
        if ($expense->user_id !== $user->id) {
            abort(403, 'Unauthorized action.');
        }

        // Ensure expense is still pending
        if ($expense->status !== 'pending') {
            return redirect()
                ->route('admin.pettycash.my-ledger')
                ->withErrors(['error' => 'Cannot edit an expense that has already been processed.']);
        }

        $request->validate([
            'date' => 'required|date|before_or_equal:today',
            'expense_account_id' => 'required|exists:accounts,id',
            'amount' => 'required|numeric|min:1',
            'is_vat_inclusive' => 'nullable|boolean',
            'vat_amount' => 'nullable|numeric|min:0',
            'amount_excluding_vat' => 'nullable|numeric|min:0',
            'description' => 'required|string|max:255',
            'receipt_images.*' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:1024', // 1MB per image
            'receipt_images' => 'nullable|array|max:3', // Max 3 images
            'delete_images' => 'nullable|array', // Images to delete
        ], [
            'date.before_or_equal' => 'You cannot add expenses for future dates.',
        ]);

        // Get existing images
        $receiptImagePaths = $expense->receipt_images ?? [];

        // Handle image deletion
        if ($request->has('delete_images')) {
            foreach ($request->delete_images as $imageToDelete) {
                // Delete from storage
                \Storage::disk('public')->delete($imageToDelete);
                // Remove from array
                $receiptImagePaths = array_values(array_filter($receiptImagePaths, function($img) use ($imageToDelete) {
                    return $img !== $imageToDelete;
                }));
            }
        }

        // Handle new file uploads
        if ($request->hasFile('receipt_images')) {
            $newImagesCount = count($receiptImagePaths) + count($request->file('receipt_images'));

            if ($newImagesCount > 3) {
                return back()->withErrors(['receipt_images' => 'You can only have a maximum of 3 images total.'])->withInput();
            }

            foreach ($request->file('receipt_images') as $image) {
                $receiptImagePaths[] = $image->store('receipts', 'public');
            }
        }

        $expense->update([
            'expense_account_id' => $request->expense_account_id,
            'expense_date' => $request->date,
            'amount' => $request->amount,
            'is_vat_inclusive' => $request->has('is_vat_inclusive'),
            'vat_amount' => $request->vat_amount ?? 0,
            'amount_excluding_vat' => $request->amount_excluding_vat ?? 0,
            'description' => $request->description,
            'receipt_images' => array_values($receiptImagePaths), // Re-index array
        ]);

        return redirect()
            ->route('admin.pettycash.my-ledger')
            ->with('success', 'Expense updated successfully');
    }




    public function storeMyExpense(Request $request)
    {
        $request->validate([
            'date' => 'required|date|before_or_equal:today',
            'expense_account_id' => 'required|exists:accounts,id',
            'amount' => 'required|numeric|min:1',
            'is_vat_inclusive' => 'nullable|boolean',
            'vat_amount' => 'nullable|numeric|min:0',
            'amount_excluding_vat' => 'nullable|numeric|min:0',
            'description' => 'required|string|max:255',
            'receipt_images.*' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:1024', // 1MB per image
            'receipt_images' => 'nullable|array|max:3', // Max 3 images
        ], [
            'date.before_or_equal' => 'You cannot add expenses for future dates.',
        ]);

        $user = Auth::user();

        $pettyCash = Account::where(
            'parent_id',
            Account::where('name', 'Petty Cash')->value('id')
        )
            ->where('user_id', $user->id)
            ->firstOrFail();

        // Handle multiple file uploads
        $receiptImagePaths = [];
        if ($request->hasFile('receipt_images')) {
            foreach ($request->file('receipt_images') as $image) {
                $receiptImagePaths[] = $image->store('receipts', 'public');
            }
        }

        PettyCashExpense::create([
            'user_id' => $user->id,
            'petty_cash_account_id' => $pettyCash->id,
            'expense_account_id' => $request->expense_account_id,
            'expense_date' => $request->date,
            'amount' => $request->amount,
            'is_vat_inclusive' => $request->has('is_vat_inclusive'),
            'vat_amount' => $request->vat_amount ?? 0,
            'amount_excluding_vat' => $request->amount_excluding_vat ?? 0,
            'description' => $request->description,
            'receipt_images' => $receiptImagePaths,
            'status' => 'pending',
        ]);

        return redirect()
            ->route('admin.pettycash.my-ledger')
            ->with('success', 'Expense submitted for approval');
    }

    public function expenseAccountSettings()
    {
        $expenseAccounts = Account::where('type', 'expense')
            ->where('is_posting', 1)
            ->orderBy('code')
            ->get();

        return view('admin.pettycash.expense-account-settings', compact('expenseAccounts'));
    }

    public function updateExpenseAccountSettings(Request $request)
    {
        $request->validate([
            'visible_accounts' => 'nullable|array',
            'visible_accounts.*' => 'exists:accounts,id',
        ]);

        // Set all expense accounts to hidden first
        Account::where('type', 'expense')
            ->where('is_posting', 1)
            ->update(['show_in_petty_cash' => false]);

        // Set selected accounts to visible
        if ($request->has('visible_accounts')) {
            Account::whereIn('id', $request->visible_accounts)
                ->update(['show_in_petty_cash' => true]);
        }

        return redirect()
            ->route('admin.pettycash.expense-account-settings')
            ->with('success', 'Expense account visibility settings updated successfully');
    }
}
