<?php

namespace App\Http\Controllers;

use App\Models\Expense;
use App\Models\ExpenseType;
use App\Models\Segment;
use App\Models\BankAccount;
use App\Models\DigitalPayment;
use App\Models\Transaction;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class ExpenseController extends Controller
{
    public function index(Request $request)
    {
        $query = Expense::where('user_id', auth()->id())
            ->with(['expenseType', 'segment', 'bankAccount', 'digitalPayment']);

        // Filter by date range
        if ($request->filled('from_date')) {
            $query->whereDate('date', '>=', $request->from_date);
        }
        if ($request->filled('to_date')) {
            $query->whereDate('date', '<=', $request->to_date);
        }

        // Filter by expense type
        if ($request->filled('expense_type_id')) {
            $query->where('expense_type_id', $request->expense_type_id);
        }

        // Filter by segment
        if ($request->filled('segment_id')) {
            $query->where('segment_id', $request->segment_id);
        }

        $expenses = $query->orderBy('date', 'desc')->paginate(20);
        $totalAmount = $query->sum('amount');

        $expenseTypes = ExpenseType::where(function ($q) {
            $q->where('user_id', auth()->id())
                ->orWhere('is_system', true);
        })->orderBy('name')->get();

        $segments = Segment::orderBy('name')->get();

        return view('expenses.index', compact('expenses', 'totalAmount', 'expenseTypes', 'segments'));
    }

    public function create()
    {
        $expenseTypes = ExpenseType::where(function ($query) {
            $query->where('user_id', auth()->id())
                ->orWhere('is_system', true);
        })->orderBy('name')->get();

        $segments = Segment::orderBy('name')->get();

        // Superadmin can see all accounts, regular users see only their own
        if (auth()->user()->isSuperAdmin()) {
            $bankAccounts = BankAccount::orderBy('bank_name')->get();
            $digitalPayments = DigitalPayment::orderBy('provider')->get();
        } else {
            $bankAccounts = auth()->user()->bankAccounts()->orderBy('bank_name')->get();
            $digitalPayments = auth()->user()->digitalPayments()->orderBy('provider')->get();
        }

        return view('expenses.create', compact('expenseTypes', 'segments', 'bankAccounts', 'digitalPayments'));
    }

    public function store(Request $request)
    {
        $validated = $request->validate([
            'date' => 'required|date',
            'expense_type_id' => 'required|exists:expense_types,id',
            'segment_id' => 'nullable|exists:segments,id',
            'amount' => 'required|numeric|min:0.01',
            'paid_amount' => 'nullable|numeric|min:0',
            'description' => 'nullable|string|max:500',
            'payment_method' => 'required|in:cash,bank,digital',
            'bank_account_id' => 'required_if:payment_method,bank|nullable|exists:bank_accounts,id',
            'digital_payment_id' => 'required_if:payment_method,digital|nullable|exists:digital_payments,id',
            'reference' => 'nullable|string|max:100',
        ]);

        // Calculate due amount and payment status
        $paidAmount = $validated['paid_amount'] ?? $validated['amount'];
        $dueAmount = max(0, $validated['amount'] - $paidAmount);

        if ($paidAmount >= $validated['amount']) {
            $paymentStatus = 'paid';
        } elseif ($paidAmount > 0) {
            $paymentStatus = 'partial';
        } else {
            $paymentStatus = 'unpaid';
        }

        try {
            DB::transaction(function () use ($validated, $paidAmount, $dueAmount, $paymentStatus) {
                $user = auth()->user();

                // Create expense with due and payment_status
                $expense = $user->expenses()->create([
                    'date' => $validated['date'],
                    'expense_type_id' => $validated['expense_type_id'],
                    'segment_id' => $validated['segment_id'] ?? null,
                    'amount' => $validated['amount'],
                    'due' => $dueAmount,
                    'payment_status' => $paymentStatus,
                    'description' => $validated['description'] ?? null,
                    'payment_method' => $validated['payment_method'],
                    'bank_account_id' => $validated['bank_account_id'] ?? null,
                    'digital_payment_id' => $validated['digital_payment_id'] ?? null,
                    'reference' => $validated['reference'] ?? null,
                ]);

                // Only create transaction and update balances if there's a paid amount
                if ($paidAmount > 0) {
                    // Create transaction record
                    $currentBalance = $this->getCurrentBalance($validated['payment_method'],
                        $validated['bank_account_id'] ?? null,
                        $validated['digital_payment_id'] ?? null);

                    $user->transactions()->create([
                        'date' => $validated['date'],
                        'type' => 'expense',
                        'payment_method' => $validated['payment_method'],
                        'bank_account_id' => $validated['bank_account_id'] ?? null,
                        'digital_payment_id' => $validated['digital_payment_id'] ?? null,
                        'expense_type_id' => $validated['expense_type_id'],
                        'amount' => $paidAmount,
                        'balance_before' => $currentBalance,
                        'balance_after' => $currentBalance - $paidAmount,
                        'details' => $validated['description'] ?? null,
                        'reference' => $validated['reference'] ?? null,
                    ]);

                    // Update account balance
                    $this->updateAccountBalance($validated['payment_method'],
                        $validated['bank_account_id'] ?? null,
                        $validated['digital_payment_id'] ?? null,
                        $currentBalance - $paidAmount);

                    // Update user total balance
                    $user->decrement('total_balance', $paidAmount);
                }
            });

            return redirect()->route('expenses.index')
                ->with('success', 'Expense recorded successfully.');
        } catch (\Exception $e) {
            return back()->withInput()->with('error', 'Failed to record expense: ' . $e->getMessage());
        }
    }

    private function getCurrentBalance($method, $bankId = null, $digitalId = null)
    {
        if ($method === 'cash') {
            $lastTransaction = Transaction::where('user_id', auth()->id())
                ->where('payment_method', 'cash')
                ->orderBy('id', 'desc')
                ->first();
            return $lastTransaction ? $lastTransaction->balance_after : 0;
        }

        if ($method === 'bank' && $bankId) {
            $account = BankAccount::find($bankId);
            return $account ? $account->balance : 0;
        }

        if ($method === 'digital' && $digitalId) {
            $account = DigitalPayment::find($digitalId);
            return $account ? $account->balance : 0;
        }

        return 0;
    }

    private function updateAccountBalance($method, $bankId = null, $digitalId = null, $newBalance)
    {
        if ($method === 'bank' && $bankId) {
            BankAccount::where('id', $bankId)->update(['balance' => $newBalance]);
        }

        if ($method === 'digital' && $digitalId) {
            DigitalPayment::where('id', $digitalId)->update(['balance' => $newBalance]);
        }
    }
}
