<?php
/**
 * Authentication helpers
 * Nazareth Church Management System
 */

require_once __DIR__ . '/permissions.php';

/**
 * Check if user is logged in. Redirect to login if not.
 * If clerk must change password, redirect to change-password.
 * Check session timeout and IP blocking.
 */
function requireAuth() {
    require_once __DIR__ . '/security.php';
    
    // Check session timeout
    if (!empty($_SESSION['user_id']) && isSessionExpired()) {
        $_SESSION = [];
        session_destroy();
        nazareth_redirect('login', ['toast_error' => 'Your session has expired due to inactivity. Please log in again.']);
        exit;
    }
    
    // Update session activity
    if (!empty($_SESSION['user_id'])) {
        updateSessionActivity();
    }
    
    if (empty($_SESSION['user_id'])) {
        nazareth_redirect('login', ['redirect' => $_SERVER['REQUEST_URI'] ?? '']);
        exit;
    }
    
    // Clerks who must change password can only access change-password
    if (!empty($_SESSION['must_change_password'])) {
        $uri = $_SERVER['REQUEST_URI'] ?? '';
        if (strpos($uri, 'change-password') === false && strpos($uri, 'logout') === false) {
            nazareth_redirect('change-password');
            exit;
        }
    }
}

/**
 * Get current user ID
 */
function currentUserId() {
    return $_SESSION['user_id'] ?? null;
}

/**
 * Get current username
 */
function currentUsername() {
    return $_SESSION['username'] ?? null;
}

/**
 * Get current user role (admin, clerk, finance, voting, or system_admin)
 */
function currentUserRole() {
    return $_SESSION['role'] ?? 'admin';
}

/**
 * Check if current user is admin (church admin)
 */
function isAdmin() {
    return currentUserRole() === 'admin';
}

/**
 * Check if current user is clerk (data entry)
 */
function isClerk() {
    return currentUserRole() === 'clerk';
}

/**
 * Check if current user is system admin (system maintenance)
 */
function isSystemAdmin() {
    return currentUserRole() === 'system_admin';
}

/**
 * Check if current user is finance (can see finance + members read-only)
 */
function isFinance() {
    return currentUserRole() === 'finance';
}

/**
 * Check if current user is voting (can manage voting system)
 */
function isVoting() {
    return currentUserRole() === 'voting';
}

/**
 * Check if current user is group manager (manages assigned generational groups only)
 */
function isGroupManager() {
    return currentUserRole() === 'group_manager';
}

/**
 * Mobile data collection team (field entry only).
 */
function isDataCollector() {
    return currentUserRole() === 'data_collector';
}

/**
 * Registration / data-collection oversight (read-only progress dashboard).
 */
function isRegCoordinator() {
    return currentUserRole() === 'reg_coordinator';
}

/**
 * Get list of fellowship names the current user is allowed to manage (empty = all for non–group_manager)
 * @return string[] Fellowship names from fellowship_managers, or empty array if not group_manager
 */
function getManagedFellowships($pdo, $userId = null) {
    if ($userId === null) $userId = currentUserId();
    if (!$userId || currentUserRole() !== 'group_manager') return [];
    try {
        $stmt = $pdo->prepare('SELECT fellowship_name FROM fellowship_managers WHERE user_id = ?');
        $stmt->execute([$userId]);
        return $stmt->fetchAll(PDO::FETCH_COLUMN);
    } catch (PDOException $e) {
        return [];
    }
}

/**
 * Require admin role. Redirect finance to /finance, voting to /voting, clerk to /members, group_manager to /fellowships, system_admin to /system.
 */
function requireAdmin() {
    $role = currentUserRole();
    if ($role === 'admin') return;
    if ($role === 'system_admin') {
        nazareth_redirect('system');
    }
    if ($role === 'group_manager') {
        nazareth_redirect('fellowships');
    }
    if ($role === 'finance') {
        nazareth_redirect('finance');
    }
    if ($role === 'voting') {
        nazareth_redirect('voting');
    }
    if ($role === 'data_collector') {
        require_once __DIR__ . '/collect-routing.php';
        nazareth_redirect(nazareth_data_collector_home_route());
    }
    if ($role === 'reg_coordinator') {
        nazareth_redirect('registration-progress');
    }
    nazareth_redirect('members');
}

/**
 * Require system admin role. Redirect others to their default pages.
 */
function requireSystemAdmin() {
    $role = currentUserRole();
    if ($role === 'system_admin') return;
    if ($role === 'admin') {
        nazareth_redirect('dashboard');
    }
    if ($role === 'group_manager') {
        nazareth_redirect('fellowships');
    }
    if ($role === 'finance') {
        nazareth_redirect('finance');
    }
    if ($role === 'voting') {
        nazareth_redirect('voting');
    }
    if ($role === 'data_collector') {
        require_once __DIR__ . '/collect-routing.php';
        nazareth_redirect(nazareth_data_collector_home_route());
    }
    if ($role === 'reg_coordinator') {
        nazareth_redirect('registration-progress');
    }
    nazareth_redirect('members');
}

/**
 * Require finance or admin (for finance section and recording offerings).
 */
function requireFinanceOrAdmin() {
    if (currentUserRole() === 'admin' || currentUserRole() === 'finance') return;
    if (currentUserRole() === 'data_collector') {
        require_once __DIR__ . '/collect-routing.php';
        nazareth_redirect(nazareth_data_collector_home_route());
    }
    if (currentUserRole() === 'reg_coordinator') {
        nazareth_redirect('registration-progress');
    }
    nazareth_redirect('members');
}

/**
 * Check if current user must change password (clerks on first login)
 */
function mustChangePassword() {
    return !empty($_SESSION['must_change_password']);
}

/**
 * Verify credentials and log in
 * @return array ['success' => bool, 'error' => string|null, 'role' => string, 'must_change_password' => bool]
 */
function attemptLogin($pdo, $username, $password) {
    require_once __DIR__ . '/audit.php';
    require_once __DIR__ . '/security.php';
    
    $ip_address = $_SERVER['REMOTE_ADDR'] ?? null;
    
    // Check IP blacklist
    if ($ip_address && isIpBlacklisted($ip_address)) {
        logFailedLogin($username, 'IP address blacklisted', $ip_address);
        return ['success' => false, 'error' => 'Access denied. Your IP address has been blocked.'];
    }
    
    // Check IP blocking (failed attempts)
    if ($ip_address && isIpBlocked($ip_address) && !isIpWhitelisted($ip_address)) {
        $attempts = getFailedLoginAttempts($ip_address);
        require_once __DIR__ . '/settings.php';
        $lockoutDuration = (int)getSetting('lockout_duration_minutes', '15');
        logFailedLogin($username, 'IP blocked due to too many failed attempts', $ip_address);
        return [
            'success' => false, 
            'error' => "Too many failed login attempts. Your IP address has been temporarily blocked for {$lockoutDuration} minutes."
        ];
    }
    
    $stmt = $pdo->prepare('SELECT id, username, password, role, must_change_password FROM users WHERE username = ? AND active = 1');
    try {
        $stmt->execute([$username]);
    } catch (PDOException $e) {
        if (strpos($e->getMessage(), 'Unknown column') !== false) {
            $stmt = $pdo->prepare('SELECT id, username, password, role FROM users WHERE username = ? AND active = 1');
            $stmt->execute([$username]);
        } else {
            throw $e;
        }
    }
    $user = $stmt->fetch();

    if (!$user || !password_verify($password, $user['password'])) {
        // Log failed login attempt
        logFailedLogin($username, 'Invalid credentials', $_SERVER['REMOTE_ADDR'] ?? null);
        return ['success' => false, 'error' => 'Invalid username or password.'];
    }

    if (session_status() === PHP_SESSION_ACTIVE) {
        session_regenerate_id(true);
    }

    $_SESSION['user_id'] = $user['id'];
    $_SESSION['username'] = $user['username'];
    $_SESSION['role'] = $user['role'] ?? 'admin';
    $_SESSION['must_change_password'] = !empty($user['must_change_password'] ?? false);
    $_SESSION['last_activity'] = time();
    
    // Log successful login
    logSuccessfulLogin($user['id'], $user['username']);
    
    return [
        'success' => true,
        'role' => $_SESSION['role'],
        'must_change_password' => $_SESSION['must_change_password'],
        'default_redirect' => nazareth_post_login_url(
            $_SESSION['role'],
            !empty($_SESSION['must_change_password'])
        ),
    ];
}

/**
 * App route to send a user to right after login (by role).
 */
function nazareth_post_login_route(?string $role = null, ?bool $mustChangePassword = null): string
{
    $role = $role ?? ($_SESSION['role'] ?? 'admin');
    $mustChangePassword = $mustChangePassword ?? !empty($_SESSION['must_change_password']);

    if ($mustChangePassword) {
        return $role === 'data_collector' ? 'mobile/change-password' : 'change-password';
    }

    switch ($role) {
        case 'system_admin':
            return 'system';
        case 'finance':
            return 'finance';
        case 'voting':
            return 'voting';
        case 'clerk':
            return 'members';
        case 'group_manager':
            return 'fellowships';
        case 'data_collector':
            require_once __DIR__ . '/device-check.php';
            return isMobileOrTablet() ? 'mobile/establish' : 'collect';
        case 'reg_coordinator':
            return 'registration-progress';
        default:
            return 'dashboard';
    }
}

/**
 * Full URL for post-login redirect.
 */
function nazareth_post_login_url(?string $role = null, ?bool $mustChangePassword = null): string
{
    return nazareth_url(nazareth_post_login_route($role, $mustChangePassword));
}

/**
 * Log out
 */
function logout() {
    $_SESSION = [];
    if (ini_get('session.use_cookies')) {
        $params = session_get_cookie_params();
        $name = session_name();
        if (PHP_VERSION_ID >= 70300) {
            setcookie($name, '', [
                'expires' => time() - 42000,
                'path' => $params['path'],
                'domain' => $params['domain'] ?? '',
                'secure' => !empty($params['secure']),
                'httponly' => !empty($params['httponly']),
                'samesite' => $params['samesite'] ?? 'Lax',
            ]);
        } else {
            setcookie($name, '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
        }
    }
    session_destroy();
}
