<?php
/* ========================
   LOGIN PROCESSOR
   Path: /pages/login_proc.php
   Updated: 2026-02-06
   Description: Unified login handler for all roles (Admin, Director, Dept Head, Staff)
======================== */

session_start();

/* ========================
   DATABASE CONNECTION
======================== */
require_once __DIR__ . '/../DataBase/koneksi.php';

/* ========================
   SECURITY HEADERS
======================== */
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Pragma: no-cache");

/* ========================
   VALIDATE REQUEST
======================== */
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    header("Location: ../index.html?error=invalid_request");
    exit;
}

/* ========================
   GET INPUT & CLIENT INFO
======================== */
$username = trim($_POST['uname'] ?? $_POST['username'] ?? '');
$password = trim($_POST['psw'] ?? $_POST['password'] ?? '');
$remember = isset($_POST['remember']);

$userIP = $_SERVER['REMOTE_ADDR'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? 'Unknown';
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';

/* ========================
   VALIDATE EMPTY FIELDS
======================== */
if (empty($username) || empty($password)) {
    header("Location: ../index.html?error=empty_fields");
    exit;
}

/* ========================
   CHECK DATABASE CONNECTION
======================== */
if (!$conn || $conn->connect_error) {
    error_log("Database connection failed: " . ($conn->connect_error ?? 'Unknown error'));
    header("Location: ../index.html?error=system_error");
    exit;
}

/* ========================
   QUERY USER FROM DATABASE
======================== */
try {
    $sql = "SELECT id, username, email, password, role, full_name, 
                   department, status, is_active, last_login
            FROM users
            WHERE (username = ? OR email = ?)
            LIMIT 1";
    
    $stmt = $conn->prepare($sql);
    
    if (!$stmt) {
        throw new Exception("Query preparation failed: " . $conn->error);
    }
    
    $stmt->bind_param('ss', $username, $username);
    $stmt->execute();
    $result = $stmt->get_result();
    $user = $result->fetch_assoc();
    $stmt->close();
    
    /* ========================
       CHECK USER EXISTS
    ======================== */
    if (!$user) {
        logFailedLogin($conn, $username, 'User not found', $userIP);
        $conn->close();
        header("Location: ../index.html?error=user_not_found");
        exit;
    }
    
    /* ========================
       CHECK ACCOUNT STATUS
       Support both 'status' and 'is_active' fields
    ======================== */
    if ((isset($user['status']) && strtolower($user['status']) !== 'active') ||
        (isset($user['is_active']) && $user['is_active'] != 1)) {
        logFailedLogin($conn, $username, 'Account inactive/suspended', $userIP);
        $conn->close();
        header("Location: ../index.html?error=account_inactive");
        exit;
    }
    
    /* ========================
       VERIFY PASSWORD
    ======================== */
    if (!password_verify($password, $user['password'])) {
        logFailedLogin($conn, $username, 'Wrong password', $userIP);
        $conn->close();
        header("Location: ../index.html?error=wrong_password");
        exit;
    }
    
    /* ========================
       NORMALIZE & VALIDATE ROLE
       Database roles: admin, director, dept_head, staff
       All roles are stored as-is in session
    ======================== */
    $userRole = strtolower(trim($user['role']));
    
    // Allowed roles from database
    $allowedRoles = ['admin', 'director', 'dept_head', 'staff'];
    
    // Validate role
    if (!in_array($userRole, $allowedRoles, true)) {
        logFailedLogin($conn, $username, 'Invalid role: ' . $userRole, $userIP);
        $conn->close();
        header("Location: ../index.html?error=invalid_role&role=" . urlencode($userRole));
        exit;
    }
    
    // Role display names
    $roleNames = [
        'admin'     => 'Administrator',
        'director'  => 'Direktur',
        'dept_head' => 'Kepala Departemen',
        'staff'     => 'Staff'
    ];
    
    /* ========================
       REGENERATE SESSION ID
       (Security: Prevent session fixation)
    ======================== */
    session_regenerate_id(true);
    
    /* ========================
       SET SESSION VARIABLES
    ======================== */
    $_SESSION['login']        = true;
    $_SESSION['user_id']      = $user['id'];
    $_SESSION['username']     = $user['username'];
    $_SESSION['full_name']    = $user['full_name'];
    $_SESSION['nama']         = $user['full_name'];           // Legacy compatibility
    $_SESSION['email']        = $user['email'];
    $_SESSION['role']         = $userRole;                    // Normalized role (admin/director/dept_head/staff)
    $_SESSION['role_name']    = $roleNames[$userRole];        // Display name
    $_SESSION['department']   = $user['department'] ?? null;
    $_SESSION['status']       = $user['status'] ?? 'active';
    $_SESSION['is_active']    = $user['is_active'] ?? 1;
    $_SESSION['user_type']    = $userRole;                    // Legacy compatibility
    $_SESSION['login_time']   = time();
    $_SESSION['last_activity']= time();
    $_SESSION['ip_address']   = $userIP;
    $_SESSION['user_agent']   = substr($userAgent, 0, 200);   // Limit length
    
    /* ========================
       REMEMBER ME FUNCTIONALITY
    ======================== */
    if ($remember) {
        $token = bin2hex(random_bytes(32));
        $hashedToken = hash('sha256', $token);
        
        // Check if remember_tokens table exists
        $checkTable = $conn->query("SHOW TABLES LIKE 'remember_tokens'");
        if ($checkTable && $checkTable->num_rows > 0) {
            $tokenStmt = $conn->prepare("
                INSERT INTO remember_tokens (user_id, token, expires_at, created_at) 
                VALUES (?, ?, DATE_ADD(NOW(), INTERVAL 30 DAY), NOW())
                ON DUPLICATE KEY UPDATE 
                    token = VALUES(token),
                    expires_at = VALUES(expires_at),
                    created_at = NOW()
            ");
            if ($tokenStmt) {
                $tokenStmt->bind_param("is", $user['id'], $hashedToken);
                $tokenStmt->execute();
                $tokenStmt->close();
            }
        }
        
        // Set secure cookie (30 days)
        setcookie('remember_token', $token, [
            'expires'  => time() + (30 * 24 * 60 * 60),
            'path'     => '/',
            'domain'   => '',
            'secure'   => isset($_SERVER['HTTPS']),  // Only HTTPS
            'httponly' => true,                       // No JavaScript access
            'samesite' => 'Strict'                    // CSRF protection
        ]);
    }
    
    /* ========================
       UPDATE LAST LOGIN
    ======================== */
    $updateStmt = $conn->prepare("
        UPDATE users 
        SET last_login = NOW(), updated_at = NOW() 
        WHERE id = ?
    ");
    if ($updateStmt) {
        $updateStmt->bind_param("i", $user['id']);
        $updateStmt->execute();
        $updateStmt->close();
    }
    
    /* ========================
       LOG SUCCESSFUL LOGIN
    ======================== */
    logSuccessfulLogin($conn, $user['id'], $user['full_name'], $userRole, $userIP, $userAgent);
    
    /* ========================
       CLOSE DATABASE
    ======================== */
    $conn->close();
    
    /* ========================
       REDIRECT TO UNIFIED DASHBOARD
       All roles (Admin, Director, Dept Head, Staff) go to dashboard.php
       Dashboard determines content based on session role
    ======================== */
    header("Location: ../dashboard.php");
    exit;
    
} catch (Exception $e) {
    // Log error for debugging
    error_log("Login error: " . $e->getMessage() . " | Stack: " . $e->getTraceAsString());
    
    // Close connection if open
    if (isset($conn) && $conn) {
        $conn->close();
    }
    
    header("Location: ../index.html?error=system_error");
    exit;
}

/* ========================
   HELPER FUNCTIONS
======================== */

/**
 * Log failed login attempt
 * 
 * @param mysqli $conn Database connection
 * @param string $username Attempted username
 * @param string $reason Failure reason
 * @param string $ip Client IP address
 */
function logFailedLogin($conn, $username, $reason, $ip) {
    try {
        // Try to use failed_logins table if exists
        $checkTable = $conn->query("SHOW TABLES LIKE 'failed_logins'");
        if ($checkTable && $checkTable->num_rows > 0) {
            $stmt = $conn->prepare("
                INSERT INTO failed_logins (username, reason, ip_address, attempted_at) 
                VALUES (?, ?, ?, NOW())
            ");
            if ($stmt) {
                $stmt->bind_param("sss", $username, $reason, $ip);
                $stmt->execute();
                $stmt->close();
            }
        }
        
        // Also log to file for debugging
        error_log("Failed Login - User: {$username}, Reason: {$reason}, IP: {$ip}");
        
    } catch (Exception $e) {
        error_log("Failed to log failed login: " . $e->getMessage());
    }
}

/**
 * Log successful login
 * 
 * @param mysqli $conn Database connection
 * @param int $userId User ID
 * @param string $userName User full name
 * @param string $role User role
 * @param string $ip Client IP address
 * @param string $userAgent Browser user agent
 */
function logSuccessfulLogin($conn, $userId, $userName, $role, $ip, $userAgent) {
    try {
        // Log to activity_log table if exists
        $checkTable = $conn->query("SHOW TABLES LIKE 'activity_log'");
        if ($checkTable && $checkTable->num_rows > 0) {
            $stmt = $conn->prepare("
                INSERT INTO activity_log 
                (user_id, action, table_name, record_id, description, ip_address, created_at) 
                VALUES (?, 'Login', 'users', ?, ?, ?, NOW())
            ");
            
            if ($stmt) {
                $browserInfo = substr($userAgent, 0, 100);
                $description = "User {$userName} (Role: {$role}) logged in successfully. Browser: {$browserInfo}";
                $stmt->bind_param("iiss", $userId, $userId, $description, $ip);
                $stmt->execute();
                $stmt->close();
            }
        }
        
        // Log to login_history table if exists
        $checkLoginHistory = $conn->query("SHOW TABLES LIKE 'login_history'");
        if ($checkLoginHistory && $checkLoginHistory->num_rows > 0) {
            $stmt = $conn->prepare("
                INSERT INTO login_history 
                (user_id, ip_address, user_agent, login_at) 
                VALUES (?, ?, ?, NOW())
            ");
            if ($stmt) {
                $stmt->bind_param("iss", $userId, $ip, $userAgent);
                $stmt->execute();
                $stmt->close();
            }
        }
        
        // Alternative: Use global logActivity function if exists
        if (function_exists('logActivity')) {
            logActivity(
                $userId, 
                'Login berhasil', 
                'users', 
                $userId, 
                "Login dari IP: {$ip}, Role: {$role}"
            );
        }
        
        // Also log successful login to file
        error_log("Successful Login - User ID: {$userId}, Name: {$userName}, Role: {$role}, IP: {$ip}");
        
    } catch (Exception $e) {
        error_log("Failed to log successful login: " . $e->getMessage());
    }
}

/* ========================
   SESSION TIMEOUT CHECK
   (Called from dashboard pages)
======================== */
function checkSessionTimeout() {
    $timeout = 7200; // 2 hours in seconds
    
    if (isset($_SESSION['last_activity'])) {
        $elapsed = time() - $_SESSION['last_activity'];
        
        if ($elapsed > $timeout) {
            session_unset();
            session_destroy();
            header("Location: index.html?error=session_timeout");
            exit;
        }
    }
    
    // Update last activity
    $_SESSION['last_activity'] = time();
}

/* ========================
   ROLE VALIDATION HELPER
   (Can be used in protected pages)
======================== */
function validateUserRole($allowedRoles = []) {
    if (!isset($_SESSION['login']) || $_SESSION['login'] !== true) {
        header("Location: index.html?error=session");
        exit;
    }
    
    if (!empty($allowedRoles)) {
        $userRole = $_SESSION['role'] ?? '';
        if (!in_array($userRole, $allowedRoles, true)) {
            header("Location: dashboard.php?error=unauthorized");
            exit;
        }
    }
    
    // Check session timeout
    checkSessionTimeout();
    
    return true;
}

/* ========================
   END OF FILE
======================== */
?>