<?php
// All Expenses — search & filter across every expense ever entered
// (Section 8, A9, Phase 6). The dashboard's Recent list is intentionally
// short; this page is the full, filterable, paginated archive.
require_once __DIR__ . '/includes/auth.php';
require_once __DIR__ . '/includes/visitor_log.php';
log_visit();
require_login();

$db = get_db();

$search = trim((string) ($_GET['search'] ?? ''));
$dateFrom = trim((string) ($_GET['date_from'] ?? ''));
$dateTo = trim((string) ($_GET['date_to'] ?? ''));
$categoryId = (int) ($_GET['category_id'] ?? 0);
$paymentMethodId = (int) ($_GET['payment_method_id'] ?? 0);
$userId = (int) ($_GET['user_id'] ?? 0);
$page = max(1, (int) ($_GET['page'] ?? 1));
$perPage = 50;

// Malformed dates are silently dropped from the filter rather than erroring
// (same "silent fallback" policy as the ?month= parameter, Section 16).
if ($dateFrom !== '' && DateTime::createFromFormat('Y-m-d', $dateFrom) === false) {
    $dateFrom = '';
}
if ($dateTo !== '' && DateTime::createFromFormat('Y-m-d', $dateTo) === false) {
    $dateTo = '';
}

$where = [];
$params = [];

if ($search !== '') {
    $where[] = 'e.description LIKE :search';
    $params['search'] = '%' . $search . '%';
}
if ($dateFrom !== '') {
    $where[] = 'e.expense_date >= :date_from';
    $params['date_from'] = $dateFrom;
}
if ($dateTo !== '') {
    $where[] = 'e.expense_date <= :date_to';
    $params['date_to'] = $dateTo;
}
if ($categoryId > 0) {
    $where[] = 'e.category_id = :category_id';
    $params['category_id'] = $categoryId;
}
if ($paymentMethodId > 0) {
    $where[] = 'e.payment_method_id = :payment_method_id';
    $params['payment_method_id'] = $paymentMethodId;
}
if ($userId > 0) {
    $where[] = 'e.user_id = :user_id';
    $params['user_id'] = $userId;
}

$whereSql = $where ? ('WHERE ' . implode(' AND ', $where)) : '';

$totalsStmt = $db->prepare("SELECT COUNT(*) AS cnt, COALESCE(SUM(e.amount), 0) AS total FROM expenses e $whereSql");
$totalsStmt->execute($params);
$totals = $totalsStmt->fetch();
$totalCount = (int) $totals['cnt'];
$totalAmountFormatted = format_money($totals['total']);

$totalPages = max(1, (int) ceil($totalCount / $perPage));
$page = min($page, $totalPages);
$offset = ($page - 1) * $perPage;

$listStmt = $db->prepare(
    "SELECT e.id, e.expense_date, e.amount, e.description, e.category_id, e.payment_method_id, e.user_id,
            c.name AS category_name, c.color AS category_color,
            u.display_name AS user_display_name
     FROM expenses e
     JOIN categories c ON c.id = e.category_id
     JOIN users u ON u.id = e.user_id
     $whereSql
     ORDER BY e.expense_date DESC, e.id DESC
     LIMIT $perPage OFFSET $offset"
);
$listStmt->execute($params);
$results = array_map('format_recent_expense_row', $listStmt->fetchAll());

// Filter dropdowns list every category/method ever used, active or not —
// a deactivated category's old expenses must stay findable (Section 9.1).
$allCategories = $db->query(
    "SELECT id, name FROM categories WHERE type = 'expense' ORDER BY sort_order"
)->fetchAll();
$allPaymentMethods = $db->query('SELECT id, name FROM payment_methods ORDER BY sort_order')->fetchAll();
$allUsers = $db->query('SELECT id, display_name FROM users ORDER BY display_name')->fetchAll();

$hasFilters = $search !== '' || $dateFrom !== '' || $dateTo !== '' || $categoryId > 0 || $paymentMethodId > 0 || $userId > 0;

/** Builds a query string from the current filters, with overrides (used for pagination links). */
function filters_query_string(array $current, array $overrides = []): string
{
    $merged = array_filter(array_merge($current, $overrides), fn ($v) => $v !== '' && $v !== 0 && $v !== null);

    return http_build_query($merged);
}

$currentFilters = [
    'search'             => $search,
    'date_from'          => $dateFrom,
    'date_to'            => $dateTo,
    'category_id'        => $categoryId ?: '',
    'payment_method_id'  => $paymentMethodId ?: '',
    'user_id'            => $userId ?: '',
];

// The edit modal (includes/layout/edit_modal.php) needs these in scope.
$categories = get_active_expense_categories();
$paymentMethods = get_active_payment_methods();
$visibleCategories = array_slice($categories, 0, 7);
$hiddenCategories = array_slice($categories, 7);

$pageTitle = 'All Expenses';
$currentPage = 'expenses';
require __DIR__ . '/includes/layout/header.php';
?>

<section class="card-x p-3 p-lg-4 mb-3 mb-lg-4" aria-label="Filters">
  <form method="get" class="row g-2 g-lg-3 align-items-end">
    <div class="col-12">
      <label class="field-label mt-0" for="search">Search description</label>
      <input class="form-control" type="text" id="search" name="search" value="<?= e($search) ?>" placeholder="e.g. lunch, rent, taxi">
    </div>
    <div class="col-6 col-md-3">
      <label class="field-label" for="date_from">From</label>
      <input class="form-control tnum" type="date" id="date_from" name="date_from" value="<?= e($dateFrom) ?>">
    </div>
    <div class="col-6 col-md-3">
      <label class="field-label" for="date_to">To</label>
      <input class="form-control tnum" type="date" id="date_to" name="date_to" value="<?= e($dateTo) ?>">
    </div>
    <div class="col-6 col-md-2">
      <label class="field-label" for="category_id">Category</label>
      <select class="form-select" id="category_id" name="category_id">
        <option value="">Any</option>
        <?php foreach ($allCategories as $cat): ?>
          <option value="<?= e((string) $cat['id']) ?>"<?= $categoryId === (int) $cat['id'] ? ' selected' : '' ?>><?= e($cat['name']) ?></option>
        <?php endforeach; ?>
      </select>
    </div>
    <div class="col-6 col-md-2">
      <label class="field-label" for="payment_method_id">Method</label>
      <select class="form-select" id="payment_method_id" name="payment_method_id">
        <option value="">Any</option>
        <?php foreach ($allPaymentMethods as $method): ?>
          <option value="<?= e((string) $method['id']) ?>"<?= $paymentMethodId === (int) $method['id'] ? ' selected' : '' ?>><?= e($method['name']) ?></option>
        <?php endforeach; ?>
      </select>
    </div>
    <div class="col-6 col-md-2">
      <label class="field-label" for="user_id">Person</label>
      <select class="form-select" id="user_id" name="user_id">
        <option value="">Any</option>
        <?php foreach ($allUsers as $u): ?>
          <option value="<?= e((string) $u['id']) ?>"<?= $userId === (int) $u['id'] ? ' selected' : '' ?>><?= e($u['display_name']) ?></option>
        <?php endforeach; ?>
      </select>
    </div>
    <div class="col-12 col-md-auto d-flex gap-2">
      <button class="btn-accent" type="submit">Filter</button>
      <?php if ($hasFilters): ?>
        <a class="btn btn-outline-secondary" href="expenses.php">Clear</a>
      <?php endif; ?>
    </div>
  </form>
</section>

<section class="card-x p-3 p-lg-4" aria-label="Results">
  <div class="d-flex align-items-baseline justify-content-between mb-2 flex-wrap gap-1">
    <div class="sec-title tnum"><?= e((string) $totalCount) ?> <?= $totalCount === 1 ? 'expense' : 'expenses' ?> · <?= e($totalAmountFormatted) ?></div>
    <?php if ($totalPages > 1): ?>
      <div class="sec-sub">Page <?= e((string) $page) ?> of <?= e((string) $totalPages) ?></div>
    <?php endif; ?>
  </div>

  <?php if (!$results): ?>
    <p class="text-secondary small mb-0">No expenses match these filters.</p>
  <?php else: ?>
    <div>
      <?php foreach ($results as $item): ?>
        <?php render_expense_row($item); ?>
      <?php endforeach; ?>
    </div>
  <?php endif; ?>

  <?php if ($totalPages > 1): ?>
    <div class="d-flex justify-content-between mt-3">
      <a class="btn btn-outline-secondary btn-sm<?= $page <= 1 ? ' disabled' : '' ?>"
         href="?<?= e(filters_query_string($currentFilters, ['page' => $page - 1])) ?>">‹ Previous</a>
      <a class="btn btn-outline-secondary btn-sm<?= $page >= $totalPages ? ' disabled' : '' ?>"
         href="?<?= e(filters_query_string($currentFilters, ['page' => $page + 1])) ?>">Next ›</a>
    </div>
  <?php endif; ?>
</section>

<?php require __DIR__ . '/includes/layout/edit_modal.php'; ?>

<!-- Toasts -->
<div class="toast-container position-fixed bottom-0 start-50 translate-middle-x p-3" id="toasts"></div>

<?php require __DIR__ . '/includes/layout/footer.php'; ?>
