<?php

namespace App\Controllers;

use App\Models\ExpenseModel;
use Config\Lookups;

/**
 * Operational expense tracking — the hotel's own costs, distinct from
 * guest-facing billing (FolioController/folios). Reachable by
 * manager/accounts (see Lookups::$permissionModules['expenses']);
 * approve/deny is manager-only (Routes.php), same boundary as shift-swap
 * and time-off approvals.
 *
 * Auto-approval: an expense under the manager-configured
 * expenses.approval_threshold_amount setting is inserted already
 * 'approved' (reviewed_by/reviewed_at set to the creator/now); at or
 * above it, it's inserted 'pending' and needs a manager's review via
 * approve()/deny() before it counts toward the P&L (see
 * ExpenseModel::totalApprovedBetween()).
 */
class ExpenseController extends BaseController
{
    public function index()
    {
        $expenses = new ExpenseModel();
        $tab      = $this->request->getGet('tab') ?: 'all';

        $builder = $expenses->withDetails();

        if (in_array($tab, ['pending', 'approved', 'denied'], true)) {
            $builder->where('expenses.status', $tab);
        }

        $list = $builder->orderBy('expenses.expense_date', 'desc')->findAll();

        return view('expenses/index', [
            'pageTitle'    => 'Expenses',
            'pageSubtitle' => "The hotel's own operating costs — utilities, payroll, supplies, and the rest.",
            'tab'          => $tab,
            'expenses'     => $list,
            'pendingCount' => (new ExpenseModel())->pendingCount(),
            'lookups'      => new Lookups(),
        ]);
    }

    public function new()
    {
        return view('expenses/form', [
            'pageTitle' => 'Log Expense',
            'lookups'   => new Lookups(),
        ]);
    }

    public function create()
    {
        $amount    = $this->request->getPost('amount');
        $threshold = (float) (service('settings')->get('expenses.approval_threshold_amount') ?: 500);
        $autoApprove = $amount !== null && (float) $amount < $threshold;

        $expenses = new ExpenseModel();
        $data = [
            'category'     => $this->request->getPost('category'),
            'description'  => $this->request->getPost('description'),
            'amount'       => $amount,
            'expense_date' => $this->request->getPost('expense_date'),
            'notes'        => $this->request->getPost('notes') ?: null,
            'created_by'   => $this->currentUserId(),
            'status'       => $autoApprove ? 'approved' : 'pending',
        ];

        if ($autoApprove) {
            $data['reviewed_by'] = $this->currentUserId();
            $data['reviewed_at'] = date('Y-m-d H:i:s');
        }

        if (! $expenses->insert($data)) {
            return $this->redirectWithModelErrors($expenses);
        }

        $expenseId = $expenses->getInsertID();

        $this->logActivity('expenses', 'Logged expense "' . $data['description'] . '" (' . format_money($amount) . ')'
            . ($autoApprove ? ', auto-approved.' : ', pending manager approval.'));

        return redirect()->to('expenses/' . $expenseId)->with('success',
            $autoApprove ? 'Expense logged and auto-approved.' : 'Expense logged — awaiting manager approval.');
    }

    public function show(int $id)
    {
        $expense = (new ExpenseModel())->withDetails()->where('expenses.id', $id)->first();

        if ($expense === null) {
            return redirect()->to('expenses')->with('error', 'Expense not found.');
        }

        return view('expenses/show', [
            'pageTitle' => 'Expense #' . $id,
            'expense'   => $expense,
            'lookups'   => new Lookups(),
        ]);
    }

    public function approve(int $id)
    {
        $expenses = new ExpenseModel();
        $expense  = $expenses->find($id);

        if ($expense === null || $expense->status !== 'pending') {
            return redirect()->back()->with('error', 'Expense not found or already reviewed.');
        }

        $expenses->update($id, ['status' => 'approved', 'reviewed_by' => $this->currentUserId(), 'reviewed_at' => date('Y-m-d H:i:s')]);
        $this->logActivity('expenses', "Approved expense #{$id} (\"{$expense->description}\", " . format_money($expense->amount) . ').');

        return redirect()->back()->with('success', 'Expense approved.');
    }

    public function deny(int $id)
    {
        $expenses = new ExpenseModel();
        $expense  = $expenses->find($id);

        if ($expense === null) {
            return redirect()->back()->with('error', 'Expense not found.');
        }

        $expenses->update($id, ['status' => 'denied', 'reviewed_by' => $this->currentUserId(), 'reviewed_at' => date('Y-m-d H:i:s')]);
        $this->logActivity('expenses', "Denied expense #{$id} (\"{$expense->description}\").");

        return redirect()->back()->with('success', 'Expense denied.');
    }
}
