<?php

namespace App\Http\Controllers\Admin\Finance;

use App\Enums\AccountCategory;
use App\Http\Controllers\Admin\PageController;
use App\Http\Requests\Finance\StoreExpenseRequest;
use App\Http\Requests\Finance\StoreSupplierRequest;
use App\Models\Account;
use App\Models\Expense;
use App\Models\Supplier;
use App\Services\Finance\DocumentNumberService;
use App\Services\Finance\ExpenseService;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\Auth;
use Illuminate\View\View;

class ExpenseController extends PageController
{
    public function __construct(
        private readonly ExpenseService $expenseService,
        private readonly DocumentNumberService $documentNumbers,
    ) {}

    public function index(): View
    {
        $expenses = Expense::query()
            ->with(['account', 'supplier', 'recordedBy'])
            ->latest('expense_date')
            ->paginate(20);

        $suppliers = Supplier::query()->orderBy('name')->get();

        return $this->page('admin.expenses.index', [
            'crumbTitle' => 'Purchases & Expenses',
            'crumbSub' => 'Purchase orders & operational spending',
            'expenses' => $expenses,
            'suppliers' => $suppliers,
        ]);
    }

    public function create(): View
    {
        return $this->page('admin.expenses.create', [
            'crumbTitle' => 'Purchases & Expenses',
            'crumbSub' => 'Record new expense',
            'suppliers' => Supplier::query()->where('status', 'active')->orderBy('name')->get(),
            'expenseAccounts' => Account::query()
                ->where('category', AccountCategory::Expense->value)
                ->orderBy('code')
                ->get(),
        ]);
    }

    public function store(StoreExpenseRequest $request): RedirectResponse
    {
        $validated = $request->validated();
        $onCredit = (bool) ($validated['on_credit'] ?? false);

        try {
            Expense::query()->create([
                'expense_number' => $this->documentNumbers->next('EXP', Expense::class, 'expense_number'),
                'supplier_id' => $validated['supplier_id'] ?? null,
                'account_id' => $validated['account_id'],
                'amount' => $validated['amount'],
                'expense_date' => $validated['expense_date'],
                'description' => $validated['description'] ?? null,
                'on_credit' => $onCredit,
                'status' => 'pending_approval',
                'recorded_by' => Auth::id(),
            ]);
        } catch (\Throwable $e) {
            return back()->withInput()->with('error', $e->getMessage());
        }

        return $this->redirectWithSuccess(
            'finance.expenses.index',
            'Expense submitted for approval.'
        );
    }

    public function approve(Expense $expense): RedirectResponse
    {
        abort_unless(auth()->user()?->can('finance.edit'), 403);

        try {
            $this->expenseService->approve($expense, auth()->user());
        } catch (\Throwable $e) {
            return back()->with('error', $e->getMessage());
        }

        return back()->with('success', "Expense {$expense->expense_number} approved and posted.");
    }

    public function reject(Expense $expense): RedirectResponse
    {
        abort_unless(auth()->user()?->can('finance.edit'), 403);

        if ($expense->journal_entry_id !== null) {
            return back()->with('error', 'Posted expenses cannot be rejected.');
        }

        $expense->update(['status' => 'rejected']);

        return back()->with('success', "Expense {$expense->expense_number} rejected.");
    }

    public function createSupplier(): View
    {
        return $this->page('admin.expenses.create-supplier', [
            'crumbTitle' => 'Purchases & Expenses',
            'crumbSub' => 'Add supplier',
        ]);
    }

    public function storeSupplier(StoreSupplierRequest $request): RedirectResponse
    {
        Supplier::query()->create(array_merge(
            $request->validated(),
            ['status' => 'active']
        ));

        return $this->redirectWithSuccess('finance.expenses.index', 'Supplier created successfully.');
    }
}
