<?php
require_once __DIR__ . '/db.php';

// ── Settings Cache ────────────────────────────────────────
/**
 * Shared in-memory cache for settings.
 * Bug Fix #6: getSetting & setSetting share this so updates are immediately visible.
 */
function _settings_cache(?string $key = null, ?string $value = null)
{
    static $cache = [];
    if ($key !== null && $value !== null) { $cache[$key] = $value; return $value; }
    if ($key !== null) { return array_key_exists($key, $cache) ? $cache[$key] : null; }
    return $cache;
}

function getSetting(string $key, $default = null)
{
    $cached = _settings_cache($key);
    if ($cached !== null) return $cached;

    $db   = getDB();
    $stmt = $db->prepare('SELECT setting_value FROM settings WHERE setting_key = ?');
    $stmt->execute([$key]);
    $row  = $stmt->fetch();
    $val  = $row ? $row['setting_value'] : $default;
    if ($row) _settings_cache($key, $val);
    return $val;
}

function setSetting(string $key, string $value): void
{
    $db = getDB();
    $db->prepare('UPDATE settings SET setting_value = ? WHERE setting_key = ?')->execute([$value, $key]);
    _settings_cache($key, $value); // Bug Fix #6: keep cache in sync
}

function getAllSettings(): array
{
    $db   = getDB();
    $rows = $db->query('SELECT * FROM settings ORDER BY id')->fetchAll();
    $out  = [];
    foreach ($rows as $r) {
        $out[$r['setting_key']] = $r;
        _settings_cache($r['setting_key'], $r['setting_value']); // warm cache
    }
    return $out;
}

// ── Card Code ─────────────────────────────────────────────
function generateCardCode(): string
{
    $db    = getDB();
    $today = date('Y-m-d');

    // Ensure both counter settings exist (safe even on old imports)
    $db->exec("
        INSERT IGNORE INTO settings (setting_key, setting_value, setting_label)
        VALUES
          ('card_counter',      '0', 'Internal Card Counter (auto)'),
          ('card_counter_date', '',  'Date of last counter reset (auto)')
    ");

    $db->beginTransaction();
    try {
        // Read current date stamp
        $stmt = $db->prepare("SELECT setting_value FROM settings WHERE setting_key = 'card_counter_date'");
        $stmt->execute();
        $counterDate = (string)$stmt->fetchColumn();

        if ($counterDate !== $today) {
            // New day — reset counter to 0 and update stamp
            $db->prepare("UPDATE settings SET setting_value = '0'    WHERE setting_key = 'card_counter'")->execute();
            $db->prepare("UPDATE settings SET setting_value = ?      WHERE setting_key = 'card_counter_date'")->execute([$today]);
        }

        // Atomic increment
        $db->exec("UPDATE settings SET setting_value = setting_value + 1 WHERE setting_key = 'card_counter'");

        // Read new value
        $stmt2 = $db->query("SELECT setting_value FROM settings WHERE setting_key = 'card_counter'");
        $counter = (int)$stmt2->fetchColumn();

        $db->commit();
    } catch (Exception $e) {
        if ($db->inTransaction()) $db->rollBack();
        throw new RuntimeException('generateCardCode failed: ' . $e->getMessage(), 0, $e);
    }

    return $today . '-' . str_pad($counter, 4, '0', STR_PAD_LEFT);
}

// ── Points ────────────────────────────────────────────────
function calculatePoints(float $amount): int
{
    $ppp = (float)(getSetting('peso_per_point') ?: 100);
    return $ppp > 0 ? (int)floor($amount / $ppp) : 0;
}

function getMemberBalance(int $memberId): int
{
    $db   = getDB();
    $stmt = $db->prepare('SELECT COALESCE(SUM(CASE WHEN type="earn" THEN points ELSE -points END),0) AS bal FROM transactions WHERE member_id = ?');
    $stmt->execute([$memberId]);
    return max(0, (int)$stmt->fetchColumn());
}

// ── Auth ──────────────────────────────────────────────────
function isLoggedIn(): bool { return !empty($_SESSION['user_id']); }
function isAdmin(): bool    { return isLoggedIn() && ($_SESSION['role'] ?? '') === 'admin'; }

function requireLogin(): void
{
    if (!isLoggedIn()) { header('Location: ' . BASE_URL . '/index.php'); exit; }
}

function requireAdmin(): void
{
    requireLogin();
    if (!isAdmin()) { header('Location: ' . BASE_URL . '/dashboard.php?err=access'); exit; }
}

// ── Member ────────────────────────────────────────────────
function getMemberByCard(string $cardCode): ?array
{
    $db   = getDB();
    $stmt = $db->prepare('SELECT * FROM members WHERE card_code = ?');
    $stmt->execute([trim($cardCode)]);
    return $stmt->fetch() ?: null;
}

// ── Helpers ───────────────────────────────────────────────
function jsonResponse(array $data, int $code = 200): void
{
    http_response_code($code);
    header('Content-Type: application/json');
    echo json_encode($data);
    exit;
}

function e(string $s): string
{
    return htmlspecialchars($s, ENT_QUOTES | ENT_HTML5, 'UTF-8');
}
