<?php
/**
 * Authentication Functions
 * OBGYN Research & Collaboration Platform
 */

/**
 * Register new user
 */
function registerUser($email, $password, $firstName, $lastName, $roleId = ROLE_RESEARCHER) {
    try {
        $db = getDB();
        
        // Check if email already exists
        $stmt = $db->prepare("SELECT id FROM users WHERE email = ?");
        $stmt->execute([$email]);
        if ($stmt->fetch()) {
            return ['success' => false, 'message' => 'Email already registered.'];
        }
        
        // Hash password
        $hashedPassword = hashPassword($password);
        
        // Generate verification token
        $verificationToken = generateToken();
        
        // Insert user
        $stmt = $db->prepare("
            INSERT INTO users (email, password, first_name, last_name, role_id, verification_token, status)
            VALUES (?, ?, ?, ?, ?, ?, 'pending')
        ");
        
        $stmt->execute([
            $email,
            $hashedPassword,
            $firstName,
            $lastName,
            $roleId,
            $verificationToken
        ]);
        
        $userId = $db->lastInsertId();
        
        // Create researcher profile if role is researcher
        if ($roleId == ROLE_RESEARCHER) {
            $stmt = $db->prepare("INSERT INTO researcher_profiles (user_id) VALUES (?)");
            $stmt->execute([$userId]);
        }
        
        // Send verification email
        $verificationLink = SITE_URL . "/verify-email.php?token=" . $verificationToken;
        $subject = "Verify Your Email - " . SITE_NAME;
        $message = "
            <html>
            <body>
                <h2>Welcome to " . SITE_NAME . "!</h2>
                <p>Thank you for registering. Please verify your email address by clicking the link below:</p>
                <p><a href='{$verificationLink}'>Verify Email Address</a></p>
                <p>Or copy and paste this link into your browser:</p>
                <p>{$verificationLink}</p>
                <p>This link will expire in 24 hours.</p>
                <p>If you did not create this account, please ignore this email.</p>
            </body>
            </html>
        ";
        
        sendEmail($email, $subject, $message);
        
        // Log activity
        logActivity('user_registered', 'users', $userId);
        
        return [
            'success' => true,
            'message' => 'Registration successful! Please check your email to verify your account.',
            'user_id' => $userId
        ];
        
    } catch (Exception $e) {
        error_log("Registration error: " . $e->getMessage());
        return ['success' => false, 'message' => 'Registration failed. Please try again.'];
    }
}

/**
 * Login user
 */
function loginUser($email, $password, $rememberMe = false) {
    try {
        $db = getDB();
        $ipAddress = $_SERVER['REMOTE_ADDR'];
        
        // Check rate limiting
        if (!checkLoginAttempts($email, $ipAddress)) {
            return ['success' => false, 'message' => 'Too many failed login attempts. Please try again later.'];
        }
        
        // Get user
        $stmt = $db->prepare("
            SELECT u.*, r.name as role_name 
            FROM users u 
            JOIN roles r ON u.role_id = r.id 
            WHERE u.email = ?
        ");
        $stmt->execute([$email]);
        $user = $stmt->fetch();
        
        if (!$user) {
            logLoginAttempt($email, $ipAddress, false);
            return ['success' => false, 'message' => 'Invalid email or password.'];
        }
        
        // Verify password
        if (!verifyPassword($password, $user['password'])) {
            logLoginAttempt($email, $ipAddress, false);
            return ['success' => false, 'message' => 'Invalid email or password.'];
        }
        
        // Check if email is verified
        if (!$user['email_verified']) {
            return ['success' => false, 'message' => 'Please verify your email address before logging in.'];
        }
        
        // Check account status
        if ($user['status'] !== 'active') {
            return ['success' => false, 'message' => 'Your account is not active. Please contact support.'];
        }
        
        // Check if 2FA is enabled
        if ($user['two_factor_enabled']) {
            // Store user ID temporarily for 2FA verification
            $_SESSION['2fa_user_id'] = $user['id'];
            $_SESSION['2fa_pending'] = true;
            return [
                'success' => true,
                'requires_2fa' => true,
                'message' => 'Please enter your 2FA code.'
            ];
        }
        
        // Log successful login
        logLoginAttempt($email, $ipAddress, true);
        
        // Update last login
        $stmt = $db->prepare("UPDATE users SET last_login = NOW() WHERE id = ?");
        $stmt->execute([$user['id']]);
        
        // Set session variables
        $_SESSION['user_id'] = $user['id'];
        $_SESSION['user_email'] = $user['email'];
        $_SESSION['user_name'] = $user['first_name'] . ' ' . $user['last_name'];
        $_SESSION['user_role'] = $user['role_id'];
        $_SESSION['user_role_name'] = $user['role_name'];
        $_SESSION['logged_in'] = true;
        
        // Handle remember me
        if ($rememberMe) {
            $token = generateToken();
            $expiry = time() + REMEMBER_ME_LIFETIME;
            
            // Store token in database (you should create a remember_tokens table)
            setcookie('remember_token', $token, $expiry, '/', '', true, true);
        }
        
        // Log activity
        logActivity('user_login', 'users', $user['id']);
        
        return [
            'success' => true,
            'message' => 'Login successful!',
            'user' => [
                'id' => $user['id'],
                'email' => $user['email'],
                'name' => $user['first_name'] . ' ' . $user['last_name'],
                'role' => $user['role_name']
            ]
        ];
        
    } catch (Exception $e) {
        error_log("Login error: " . $e->getMessage());
        return ['success' => false, 'message' => 'Login failed. Please try again.'];
    }
}

/**
 * Verify 2FA and complete login
 */
function verify2FAAndLogin($code) {
    try {
        if (!isset($_SESSION['2fa_pending']) || !isset($_SESSION['2fa_user_id'])) {
            return ['success' => false, 'message' => 'Invalid 2FA session.'];
        }
        
        $db = getDB();
        $userId = $_SESSION['2fa_user_id'];
        
        // Get user's 2FA secret
        $stmt = $db->prepare("SELECT * FROM users WHERE id = ?");
        $stmt->execute([$userId]);
        $user = $stmt->fetch();
        
        if (!$user || !$user['two_factor_enabled']) {
            return ['success' => false, 'message' => 'Invalid 2FA configuration.'];
        }
        
        // Verify code
        if (!verify2FACode($user['two_factor_secret'], $code)) {
            return ['success' => false, 'message' => 'Invalid 2FA code.'];
        }
        
        // Clear 2FA session variables
        unset($_SESSION['2fa_pending']);
        unset($_SESSION['2fa_user_id']);
        
        // Set regular session variables
        $_SESSION['user_id'] = $user['id'];
        $_SESSION['user_email'] = $user['email'];
        $_SESSION['user_name'] = $user['first_name'] . ' ' . $user['last_name'];
        $_SESSION['user_role'] = $user['role_id'];
        $_SESSION['logged_in'] = true;
        
        // Update last login
        $stmt = $db->prepare("UPDATE users SET last_login = NOW() WHERE id = ?");
        $stmt->execute([$user['id']]);
        
        // Log activity
        logActivity('user_login_2fa', 'users', $user['id']);
        
        return ['success' => true, 'message' => 'Login successful!'];
        
    } catch (Exception $e) {
        error_log("2FA verification error: " . $e->getMessage());
        return ['success' => false, 'message' => '2FA verification failed.'];
    }
}

/**
 * Logout user
 */
function logoutUser() {
    try {
        $userId = getCurrentUserId();
        
        // Log activity
        if ($userId) {
            logActivity('user_logout', 'users', $userId);
        }
        
        // Clear remember me cookie
        if (isset($_COOKIE['remember_token'])) {
            setcookie('remember_token', '', time() - 3600, '/', '', true, true);
        }
        
        // Destroy session
        session_unset();
        session_destroy();
        
        return ['success' => true, 'message' => 'Logged out successfully.'];
        
    } catch (Exception $e) {
        error_log("Logout error: " . $e->getMessage());
        return ['success' => false, 'message' => 'Logout failed.'];
    }
}

/**
 * Verify email with token
 */
function verifyEmail($token) {
    try {
        $db = getDB();
        
        // Find user with token
        $stmt = $db->prepare("
            SELECT id FROM users 
            WHERE verification_token = ? 
            AND email_verified = 0 
            AND created_at > DATE_SUB(NOW(), INTERVAL 24 HOUR)
        ");
        $stmt->execute([$token]);
        $user = $stmt->fetch();
        
        if (!$user) {
            return ['success' => false, 'message' => 'Invalid or expired verification token.'];
        }
        
        // Update user
        $stmt = $db->prepare("
            UPDATE users 
            SET email_verified = 1, 
                verification_token = NULL, 
                status = 'active' 
            WHERE id = ?
        ");
        $stmt->execute([$user['id']]);
        
        // Log activity
        logActivity('email_verified', 'users', $user['id']);
        
        return ['success' => true, 'message' => 'Email verified successfully! You can now login.'];
        
    } catch (Exception $e) {
        error_log("Email verification error: " . $e->getMessage());
        return ['success' => false, 'message' => 'Email verification failed.'];
    }
}

/**
 * Request password reset
 */
function requestPasswordReset($email) {
    try {
        $db = getDB();
        
        // Check if user exists
        $stmt = $db->prepare("SELECT id, first_name FROM users WHERE email = ?");
        $stmt->execute([$email]);
        $user = $stmt->fetch();
        
        if (!$user) {
            // Don't reveal if email exists or not
            return ['success' => true, 'message' => 'If the email exists, a reset link has been sent.'];
        }
        
        // Generate reset token
        $resetToken = generateToken();
        $expiry = date('Y-m-d H:i:s', strtotime('+1 hour'));
        
        // Update user
        $stmt = $db->prepare("
            UPDATE users 
            SET reset_token = ?, reset_token_expiry = ? 
            WHERE id = ?
        ");
        $stmt->execute([$resetToken, $expiry, $user['id']]);
        
        // Send reset email
        $resetLink = SITE_URL . "/reset-password.php?token=" . $resetToken;
        $subject = "Password Reset Request - " . SITE_NAME;
        $message = "
            <html>
            <body>
                <h2>Password Reset Request</h2>
                <p>Hi {$user['first_name']},</p>
                <p>We received a request to reset your password. Click the link below to reset it:</p>
                <p><a href='{$resetLink}'>Reset Password</a></p>
                <p>Or copy and paste this link into your browser:</p>
                <p>{$resetLink}</p>
                <p>This link will expire in 1 hour.</p>
                <p>If you did not request this reset, please ignore this email.</p>
            </body>
            </html>
        ";
        
        sendEmail($email, $subject, $message);
        
        // Log activity
        logActivity('password_reset_requested', 'users', $user['id']);
        
        return ['success' => true, 'message' => 'If the email exists, a reset link has been sent.'];
        
    } catch (Exception $e) {
        error_log("Password reset request error: " . $e->getMessage());
        return ['success' => false, 'message' => 'Password reset request failed.'];
    }
}

/**
 * Reset password with token
 */
function resetPassword($token, $newPassword) {
    try {
        $db = getDB();
        
        // Find user with valid token
        $stmt = $db->prepare("
            SELECT id FROM users 
            WHERE reset_token = ? 
            AND reset_token_expiry > NOW()
        ");
        $stmt->execute([$token]);
        $user = $stmt->fetch();
        
        if (!$user) {
            return ['success' => false, 'message' => 'Invalid or expired reset token.'];
        }
        
        // Validate password strength
        $validation = validatePasswordStrength($newPassword);
        if (!$validation['valid']) {
            return ['success' => false, 'message' => implode(' ', $validation['errors'])];
        }
        
        // Hash new password
        $hashedPassword = hashPassword($newPassword);
        
        // Update user
        $stmt = $db->prepare("
            UPDATE users 
            SET password = ?, 
                reset_token = NULL, 
                reset_token_expiry = NULL 
            WHERE id = ?
        ");
        $stmt->execute([$hashedPassword, $user['id']]);
        
        // Log activity
        logActivity('password_reset', 'users', $user['id']);
        
        return ['success' => true, 'message' => 'Password reset successfully! You can now login.'];
        
    } catch (Exception $e) {
        error_log("Password reset error: " . $e->getMessage());
        return ['success' => false, 'message' => 'Password reset failed.'];
    }
}

/**
 * Change password (for logged in users)
 */
function changePassword($userId, $currentPassword, $newPassword) {
    try {
        $db = getDB();
        
        // Get current password hash
        $stmt = $db->prepare("SELECT password FROM users WHERE id = ?");
        $stmt->execute([$userId]);
        $user = $stmt->fetch();
        
        if (!$user) {
            return ['success' => false, 'message' => 'User not found.'];
        }
        
        // Verify current password
        if (!verifyPassword($currentPassword, $user['password'])) {
            return ['success' => false, 'message' => 'Current password is incorrect.'];
        }
        
        // Validate new password strength
        $validation = validatePasswordStrength($newPassword);
        if (!$validation['valid']) {
            return ['success' => false, 'message' => implode(' ', $validation['errors'])];
        }
        
        // Hash new password
        $hashedPassword = hashPassword($newPassword);
        
        // Update password
        $stmt = $db->prepare("UPDATE users SET password = ? WHERE id = ?");
        $stmt->execute([$hashedPassword, $userId]);
        
        // Log activity
        logActivity('password_changed', 'users', $userId);
        
        return ['success' => true, 'message' => 'Password changed successfully!'];
        
    } catch (Exception $e) {
        error_log("Password change error: " . $e->getMessage());
        return ['success' => false, 'message' => 'Password change failed.'];
    }
}

/**
 * Get user by ID
 */
function getUserById($userId) {
    try {
        $db = getDB();
        $stmt = $db->prepare("
            SELECT u.*, r.name as role_name 
            FROM users u 
            JOIN roles r ON u.role_id = r.id 
            WHERE u.id = ?
        ");
        $stmt->execute([$userId]);
        return $stmt->fetch();
    } catch (Exception $e) {
        error_log("Get user error: " . $e->getMessage());
        return null;
    }
}

/**
 * Update user profile
 */
function updateUserProfile($userId, $data) {
    try {
        $db = getDB();
        
        $allowedFields = ['first_name', 'last_name', 'email'];
        $updates = [];
        $values = [];
        
        foreach ($allowedFields as $field) {
            if (isset($data[$field])) {
                $updates[] = "$field = ?";
                $values[] = $data[$field];
            }
        }
        
        if (empty($updates)) {
            return ['success' => false, 'message' => 'No fields to update.'];
        }
        
        $values[] = $userId;
        $sql = "UPDATE users SET " . implode(', ', $updates) . " WHERE id = ?";
        
        $stmt = $db->prepare($sql);
        $stmt->execute($values);
        
        // Log activity
        logActivity('profile_updated', 'users', $userId, null, $data);
        
        return ['success' => true, 'message' => 'Profile updated successfully!'];
        
    } catch (Exception $e) {
        error_log("Profile update error: " . $e->getMessage());
        return ['success' => false, 'message' => 'Profile update failed.'];
    }
}

/**
 * Check if user has permission
 */
function userHasPermission($userId, $permission) {
    try {
        $db = getDB();
        $stmt = $db->prepare("
            SELECT COUNT(*) 
            FROM users u
            JOIN role_permissions rp ON u.role_id = rp.role_id
            JOIN permissions p ON rp.permission_id = p.id
            WHERE u.id = ? AND p.name = ?
        ");
        $stmt->execute([$userId, $permission]);
        return $stmt->fetchColumn() > 0;
    } catch (Exception $e) {
        error_log("Permission check error: " . $e->getMessage());
        return false;
    }
}
?>
