<?php
declare(strict_types=1);

namespace App\Controllers\Web;

use App\Middleware\AuthSession;
use App\Middleware\TenantScope;
use App\Lib\Pdf;
use App\Models\Asset;
use App\Models\Attachment;
use App\Models\Expense;
use App\Models\Site;
use App\Models\Tenant;
use App\Models\WorkOrder;
use Core\Controller;
use Core\Session;
use Core\Tool;

final class ExpensesController extends Controller
{
    public function middleware(): array
    {
        return [AuthSession::class, TenantScope::class];
    }

    private function tenantId(): int
    {
        return (int) ($_SESSION['tenant_id'] ?? 0);
    }

    public function index(): void
    {
        $tenantId = $this->tenantId();
        $filters = [
            'status'       => $_GET['status']       ?? null,
            'category_id'  => $_GET['category_id']  ?? null,
            'submitted_by' => $_GET['submitted_by'] ?? null,
            'q'            => $_GET['q']            ?? null,
        ];
        $this->render('expenses/index', [
            'expenses'   => Expense::listForTenant($tenantId, array_filter($filters)),
            'categories' => Expense::categoriesFor($tenantId),
            'filters'    => $filters,
            'flash'      => Session::flash('exp_msg'),
        ]);
    }

    public function create(): void
    {
        $tenantId = $this->tenantId();
        $this->render('expenses/form', [
            'expense'    => null,
            'categories' => Expense::categoriesFor($tenantId),
            'sites'      => Site::optionsForTenant($tenantId),
            'assets'     => Asset::optionsForTenant($tenantId),
            'workOrders' => WorkOrder::listForTenant($tenantId, []),
            'csrf'       => Tool::generateCsrf(),
        ]);
    }

    public function edit(int $id): void
    {
        $tenantId = $this->tenantId();
        $exp = Expense::findInTenant($tenantId, $id);
        if (!$exp) { Session::flash('exp_msg', 'Expense not found.'); redirect('/Expenses'); }
        $this->render('expenses/form', [
            'expense'    => $exp,
            'categories' => Expense::categoriesFor($tenantId),
            'sites'      => Site::optionsForTenant($tenantId),
            'assets'     => Asset::optionsForTenant($tenantId),
            'workOrders' => WorkOrder::listForTenant($tenantId, []),
            'csrf'       => Tool::generateCsrf(),
        ]);
    }

    public function save(): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') redirect('/Expenses');
        if (!Tool::checkCsrf($_POST['_csrf'] ?? null)) {
            Session::flash('exp_msg', 'Session expired.'); redirect('/Expenses');
        }
        $tenantId = $this->tenantId();
        $userId   = (int) (Session::user()['user_id'] ?? 0);
        $id       = (int) ($_POST['expense_id'] ?? 0);

        if (trim((string) ($_POST['title'] ?? '')) === '' || !is_numeric($_POST['amount'] ?? null)) {
            Session::flash('exp_msg', 'Title and numeric amount are required.');
            redirect($id > 0 ? "/Expenses/edit/{$id}" : '/Expenses/create');
        }

        if ($id > 0) {
            Expense::update($tenantId, $id, $_POST);
            Session::flash('exp_msg', 'Expense updated.');
        } else {
            $id = Expense::create($tenantId, $userId, $_POST);
            Session::flash('exp_msg', 'Expense created.');
        }
        redirect("/Expenses/show/{$id}");
    }

    public function show(int $id): void
    {
        $tenantId = $this->tenantId();
        $exp = Expense::findInTenant($tenantId, $id);
        if (!$exp) { Session::flash('exp_msg', 'Not found.'); redirect('/Expenses'); }
        $this->render('expenses/show', [
            'expense'     => $exp,
            'attachments' => Attachment::forOwner($tenantId, 'expense', $id),
            'ownerType'   => 'expense',
            'ownerId'     => $id,
            'flash'       => Session::flash('exp_msg') ?: Session::flash('attach_msg'),
            'csrf'        => Tool::generateCsrf(),
        ]);
    }

    public function transition(int $id): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? '') !== 'POST') redirect("/Expenses/show/{$id}");
        if (!Tool::checkCsrf($_POST['_csrf'] ?? null)) redirect("/Expenses/show/{$id}");
        $tenantId = $this->tenantId();
        $userId   = (int) (Session::user()['user_id'] ?? 0);
        $status   = (string) ($_POST['status'] ?? '');
        $note     = trim((string) ($_POST['approval_note'] ?? '')) ?: null;
        Expense::transition($tenantId, $id, $status, $userId, $note);
        Session::flash('exp_msg', 'Status changed to ' . $status . '.');
        redirect("/Expenses/show/{$id}");
    }

    public function delete(int $id): void
    {
        Expense::softDelete($this->tenantId(), $id);
        Session::flash('exp_msg', 'Expense deleted.');
        redirect('/Expenses');
    }

    public function pdf(int $id): void
    {
        $tenantId = $this->tenantId();
        $expense = Expense::findInTenant($tenantId, $id);
        if (!$expense) { http_response_code(404); echo 'Not found'; return; }
        $tenant = Tenant::findById($tenantId);
        ob_start();
        require ROOT . '/app/Views/pdf/expense.php';
        $html = ob_get_clean();
        Pdf::stream($html, 'EXP-' . ($expense['code'] ?: $id));
    }
}
