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

// ============================================================
//  Authentication — Phase 2e
// ============================================================
//  Members and admins are now COMPLETELY separate:
//    - members  → $_SESSION['member_id']
//    - admins   → $_SESSION['admin_id']
//
//  Both sessions can co-exist (someone could be logged into both
//  a member account and an admin account in different tabs).
//
//  Public functions:
//
//    Member side:
//      auth_login_member($email, $password)  → array|null
//      auth_logout_member()
//      auth_member_check()                   → bool
//      auth_member_id()                      → int|null
//      auth_member_user()                    → array|null
//      auth_require_member()                 → guard
//
//    Admin side:
//      auth_login_admin($email, $password)   → array|null
//      auth_logout_admin()
//      auth_admin_check()                    → bool
//      auth_admin_id()                       → int|null
//      auth_admin_user()                     → array|null
//      auth_require_admin()                  → guard
//      auth_require_super_admin()            → guard for sensitive ops
//
//    Backwards-compat aliases (so older code still works):
//      auth_login()      → auth_login_member()
//      auth_check()      → auth_member_check()
//      auth_id()         → auth_member_id()
//      auth_user()       → auth_member_user()
//      auth_require_login() → auth_require_member()
//
//  Password reset is supported on BOTH systems with separate tables.
// ============================================================

// ─────────────────────────────────────────────────────────────
//  MEMBER auth
// ─────────────────────────────────────────────────────────────

function auth_login_member(string $email, string $password): ?array {
    $member = db_row(
        'SELECT * FROM members WHERE email = :email LIMIT 1',
        ['email' => strtolower(trim($email))]
    );
    if (!$member)                                              return null;
    if ($member['status'] === 'suspended')                     return null;
    if (!password_verify($password, $member['password_hash'])) return null;

    session_start_once();
    session_regenerate_id(true);
    $_SESSION['member_id']    = (int)$member['id'];
    $_SESSION['member_email'] = $member['email'];
    csrf_rotate();

    try {
        db_exec('UPDATE members SET last_login_at = NOW() WHERE id = :id',
                ['id' => $member['id']]);
    } catch (Throwable $e) { /* ignore */ }

    return $member;
}

function auth_logout_member(): void {
    session_start_once();
    unset($_SESSION['member_id'], $_SESSION['member_email']);
    // Don't destroy the session — they might also be logged in as admin
    csrf_rotate();
}

function auth_member_check(): bool {
    session_start_once();
    return !empty($_SESSION['member_id']);
}

function auth_member_id(): ?int {
    session_start_once();
    return isset($_SESSION['member_id']) ? (int)$_SESSION['member_id'] : null;
}

function auth_member_user(): ?array {
    static $cache = null;
    if ($cache !== null) return $cache ?: null;

    $id = auth_member_id();
    if (!$id) { $cache = false; return null; }

    $cache = db_row('SELECT * FROM members WHERE id = :id', ['id' => $id]);
    return $cache ?: null;
}

function auth_require_member(): void {
    if (!auth_member_check()) {
        $next = urlencode($_SERVER['REQUEST_URI'] ?? '');
        header('Location: ' . (defined('SITE_URL') ? SITE_URL : '') . '/login.php?next=' . $next);
        exit;
    }
}

// ─────────────────────────────────────────────────────────────
//  ADMIN auth
// ─────────────────────────────────────────────────────────────

function auth_login_admin(string $email, string $password): ?array {
    $admin = db_row(
        'SELECT * FROM admin_users WHERE email = :email LIMIT 1',
        ['email' => strtolower(trim($email))]
    );
    if (!$admin)                                              return null;
    if ((int)$admin['active'] !== 1)                          return null;
    if (!password_verify($password, $admin['password_hash'])) return null;

    session_start_once();
    session_regenerate_id(true);
    $_SESSION['admin_id']    = (int)$admin['id'];
    $_SESSION['admin_email'] = $admin['email'];
    $_SESSION['admin_role']  = $admin['role'];
    csrf_rotate();

    try {
        db_exec('UPDATE admin_users SET last_login_at = NOW() WHERE id = :id',
                ['id' => $admin['id']]);
    } catch (Throwable $e) { /* ignore */ }

    return $admin;
}

function auth_logout_admin(): void {
    session_start_once();
    unset($_SESSION['admin_id'], $_SESSION['admin_email'], $_SESSION['admin_role']);
    csrf_rotate();
}

function auth_admin_check(): bool {
    session_start_once();
    return !empty($_SESSION['admin_id']);
}

function auth_admin_id(): ?int {
    session_start_once();
    return isset($_SESSION['admin_id']) ? (int)$_SESSION['admin_id'] : null;
}

function auth_admin_user(): ?array {
    static $cache = null;
    if ($cache !== null) return $cache ?: null;

    $id = auth_admin_id();
    if (!$id) { $cache = false; return null; }

    $cache = db_row('SELECT * FROM admin_users WHERE id = :id', ['id' => $id]);
    return $cache ?: null;
}

function auth_require_admin(): void {
    if (!auth_admin_check()) {
        $next = urlencode($_SERVER['REQUEST_URI'] ?? '');
        header('Location: ' . (defined('SITE_URL') ? SITE_URL : '') . '/admin/login.php?next=' . $next);
        exit;
    }
    // Verify the admin still exists and is active
    $u = auth_admin_user();
    if (!$u || (int)$u['active'] !== 1) {
        auth_logout_admin();
        header('Location: ' . (defined('SITE_URL') ? SITE_URL : '') . '/admin/login.php');
        exit;
    }
}

function auth_require_super_admin(): void {
    auth_require_admin();
    $u = auth_admin_user();
    if (!$u || $u['role'] !== 'super_admin') {
        http_response_code(403);
        echo 'Super admin access required.';
        exit;
    }
}

// ─────────────────────────────────────────────────────────────
//  Backwards-compat aliases (so older files keep working)
// ─────────────────────────────────────────────────────────────

if (!function_exists('auth_login')) {
    function auth_login(string $email, string $password): ?array {
        return auth_login_member($email, $password);
    }
}
if (!function_exists('auth_logout')) {
    function auth_logout(): void {
        // Old code that called auth_logout() probably expects a full logout
        session_start_once();
        $_SESSION = [];
        if (ini_get('session.use_cookies')) {
            $params = session_get_cookie_params();
            setcookie(session_name(), '', time() - 42000,
                $params['path'], $params['domain'],
                $params['secure'], $params['httponly']);
        }
        session_destroy();
    }
}
if (!function_exists('auth_check')) {
    function auth_check(): bool { return auth_member_check(); }
}
if (!function_exists('auth_id')) {
    function auth_id(): ?int { return auth_member_id(); }
}
if (!function_exists('auth_user')) {
    function auth_user(): ?array { return auth_member_user(); }
}
if (!function_exists('auth_require_login')) {
    function auth_require_login(): void { auth_require_member(); }
}

// ─────────────────────────────────────────────────────────────
//  Password reset — MEMBER
// ─────────────────────────────────────────────────────────────

function auth_create_reset_token(string $email): ?string {
    $member = db_row(
        'SELECT id FROM members WHERE email = :email LIMIT 1',
        ['email' => strtolower(trim($email))]
    );
    if (!$member) return null;

    $raw    = bin2hex(random_bytes(32));
    $hashed = hash('sha256', $raw);

    db_insert('password_resets', [
        'token'      => $hashed,
        'member_id'  => $member['id'],
        'expires_at' => date('Y-m-d H:i:s', time() + (defined('AUTH_RESET_LIFE') ? AUTH_RESET_LIFE : 3600)),
    ]);
    return $raw;
}

function auth_consume_reset_token(string $raw): ?array {
    $hashed = hash('sha256', $raw);
    $row = db_row(
        'SELECT m.* FROM password_resets pr
            JOIN members m ON m.id = pr.member_id
            WHERE pr.token = :t
              AND pr.used_at IS NULL
              AND pr.expires_at > NOW()
            LIMIT 1',
        ['t' => $hashed]
    );
    if (!$row) return null;

    db_exec('UPDATE password_resets SET used_at = NOW() WHERE token = :t',
            ['t' => $hashed]);
    return $row;
}

function auth_set_password(int $member_id, string $new_password): void {
    $cost = defined('AUTH_BCRYPT_COST') ? AUTH_BCRYPT_COST : 12;
    $hash = password_hash($new_password, PASSWORD_BCRYPT, ['cost' => $cost]);
    db_exec('UPDATE members SET password_hash = :h WHERE id = :id',
            ['h' => $hash, 'id' => $member_id]);
}

// ─────────────────────────────────────────────────────────────
//  Password reset — ADMIN (uses admin_users.reset_token directly)
// ─────────────────────────────────────────────────────────────

function auth_admin_create_reset_token(string $email): ?string {
    $admin = db_row(
        'SELECT id FROM admin_users WHERE email = :email AND active = 1 LIMIT 1',
        ['email' => strtolower(trim($email))]
    );
    if (!$admin) return null;

    $raw    = bin2hex(random_bytes(32));
    $hashed = hash('sha256', $raw);
    db_exec(
        'UPDATE admin_users SET reset_token = :t, reset_expires = DATE_ADD(NOW(), INTERVAL 1 HOUR) WHERE id = :id',
        ['t' => $hashed, 'id' => $admin['id']]
    );
    return $raw;
}

function auth_admin_consume_reset_token(string $raw): ?array {
    $hashed = hash('sha256', $raw);
    $admin = db_row(
        'SELECT * FROM admin_users
          WHERE reset_token = :t
            AND reset_expires > NOW()
            AND active = 1
          LIMIT 1',
        ['t' => $hashed]
    );
    if (!$admin) return null;
    db_exec(
        'UPDATE admin_users SET reset_token = NULL, reset_expires = NULL WHERE id = :id',
        ['id' => $admin['id']]
    );
    return $admin;
}

function auth_admin_set_password(int $admin_id, string $new_password): void {
    $cost = defined('AUTH_BCRYPT_COST') ? AUTH_BCRYPT_COST : 12;
    $hash = password_hash($new_password, PASSWORD_BCRYPT, ['cost' => $cost]);
    db_exec('UPDATE admin_users SET password_hash = :h WHERE id = :id',
            ['h' => $hash, 'id' => $admin_id]);
}