<?php
/**
 * Configuration File - COMPLETE WORKING VERSION
 */

// =============================================
// SESSION CONFIGURATION - MUST BE FIRST
// =============================================

// Set session parameters BEFORE session starts
ini_set('session.name', 'NIS_AMS_SESSION');
ini_set('session.cookie_httponly', 1);
ini_set('session.use_only_cookies', 1);
ini_set('session.cookie_secure', 0);
ini_set('session.cookie_samesite', 'Strict');
ini_set('session.gc_maxlifetime', 1800);

// =============================================
// DATABASE CONFIGURATION
// =============================================

define('DB_HOST', 'localhost');
define('DB_NAME', 'nismigra_ams');
define('DB_USER', 'nismigra_nismigra');
define('DB_PASS', '4zXsR7CO:7lw@2');
define('DB_CHARSET', 'utf8mb4');

// =============================================
// APPLICATION CONFIGURATION
// =============================================

define('APP_NAME', 'NIS Asset Management System');
define('APP_URL', 'https://nis-migrant.com.ng/nis_ams');
define('BASE_URL', APP_URL); // CRITICAL: Your header uses BASE_URL
define('APP_ENV', 'production');

// =============================================
// SECURITY CONFIGURATION
// =============================================

define('CSRF_TOKEN_NAME', 'csrf_token');
define('SESSION_LIFETIME', 1800);

// =============================================
// FUNCTION DEFINITIONS
// =============================================

/**
 * Generate CSRF token
 */
function generateCSRFToken() {
    if (!isset($_SESSION[CSRF_TOKEN_NAME])) {
        $_SESSION[CSRF_TOKEN_NAME] = bin2hex(random_bytes(32));
    }
    return $_SESSION[CSRF_TOKEN_NAME];
}

/**
 * Verify CSRF token
 */
function verifyCSRFToken($token) {
    if (!isset($_SESSION[CSRF_TOKEN_NAME]) || $token !== $_SESSION[CSRF_TOKEN_NAME]) {
        return false;
    }
    return true;
}

/**
 * Get database connection
 */
function getDBConnection() {
    try {
        $dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
        $pdo = new PDO($dsn, DB_USER, DB_PASS);
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
        return $pdo;
    } catch (PDOException $e) {
        error_log("Database connection failed: " . $e->getMessage());
        return null;
    }
}

/**
 * Initialize session
 */
function initSession() {
    if (session_status() === PHP_SESSION_NONE) {
        session_start();
    }
    
    if (!isset($_SESSION['_last_regenerate']) || time() - $_SESSION['_last_regenerate'] > 300) {
        session_regenerate_id(true);
        $_SESSION['_last_regenerate'] = time();
    }
}

/**
 * Check if user is logged in
 */
function isLoggedIn() {
    return isset($_SESSION['user_id']) && isset($_SESSION['logged_in']) && $_SESSION['logged_in'] === true;
}

/**
 * Require login
 */
function requireLogin() {
    if (!isLoggedIn()) {
        header('Location: ' . APP_URL . '/index.php?error=' . urlencode('Please login to access this page'));
        exit;
    }
}

/**
 * Get current user data
 */
function getCurrentUser() {
    if (!isLoggedIn()) {
        return null;
    }
    
    return [
        'id' => $_SESSION['user_id'],
        'username' => $_SESSION['username'],
        'full_name' => $_SESSION['full_name'],
        'email' => $_SESSION['email'],
        'rank' => $_SESSION['rank'],
        'nis_number' => $_SESSION['nis_number'],
        'roles' => $_SESSION['roles'] ?? [],
        'permissions' => $_SESSION['permissions'] ?? []
    ];
}

/**
 * Check if user has a specific role
 */
function hasRole($role) {
    if (!isLoggedIn()) return false;
    $roles = $_SESSION['roles'] ?? [];
    return in_array($role, $roles);
}

/**
 * Check if user has any of the given roles
 */
function hasAnyRole($roles) {
    if (!isLoggedIn()) return false;
    $userRoles = $_SESSION['roles'] ?? [];
    foreach ($roles as $role) {
        if (in_array($role, $userRoles)) return true;
    }
    return false;
}

/**
 * Check if user has permission
 */
function hasPermission($permission) {
    if (!isLoggedIn()) return false;
    if (hasRole('Super Admin Officer')) return true;
    $permissions = $_SESSION['permissions'] ?? [];
    return in_array($permission, $permissions);
}

/**
 * Redirect with message
 */
function redirect($url, $message = null, $type = 'error') {
    if ($message) {
        $url .= (strpos($url, '?') === false ? '?' : '&') . $type . '=' . urlencode($message);
    }
    header('Location: ' . APP_URL . '/' . ltrim($url, '/'));
    exit;
}

/**
 * Get user roles from database
 */
function getUserRoles($userId, $pdo) {
    try {
        $stmt = $pdo->prepare("SELECT r.role_name, r.id FROM user_roles ur JOIN roles r ON ur.role_id = r.id WHERE ur.user_id = ?");
        $stmt->execute([$userId]);
        return $stmt->fetchAll();
    } catch (Exception $e) {
        return [];
    }
}

/**
 * Get user permissions from database
 */
function getUserPermissions($userId, $pdo) {
    try {
        $stmt = $pdo->prepare("
            SELECT DISTINCT p.permission_key 
            FROM permissions p
            JOIN role_permissions rp ON p.id = rp.permission_id
            JOIN user_roles ur ON rp.role_id = ur.role_id
            WHERE ur.user_id = ? AND (rp.can_view = 1 OR rp.can_create = 1 OR rp.can_edit = 1 OR rp.can_delete = 1 OR rp.can_approve = 1)
        ");
        $stmt->execute([$userId]);
        $results = $stmt->fetchAll();
        return array_column($results, 'permission_key');
    } catch (Exception $e) {
        return [];
    }
}

// =============================================
// CLASS DEFINITIONS
// =============================================

class Auth {
    public static function check() { return isLoggedIn(); }
    public static function id() { return $_SESSION['user_id'] ?? null; }
    public static function user() { return getCurrentUser(); }
    public static function hasRole($role) { return hasRole($role); }
    public static function hasAnyRole($roles) { return hasAnyRole($roles); }
    public static function can($permission) { return hasPermission($permission); }
    public static function canAny($permissions) {
        if (!isLoggedIn()) return false;
        if (hasRole('Super Admin Officer')) return true;
        $userPermissions = $_SESSION['permissions'] ?? [];
        foreach ($permissions as $permission) {
            if (in_array($permission, $userPermissions)) return true;
        }
        return false;
    }
    public static function requireAuth() { requireLogin(); }
}

class Security {
    public static function csrfToken() { return generateCSRFToken(); }
    public static function validateCsrfToken($token) { return verifyCSRFToken($token); }
    public static function csrfField() { return '<input type="hidden" name="csrf_token" value="' . self::csrfToken() . '">'; }
    public static function escape($data) {
        if (is_array($data)) return array_map([self::class, 'escape'], $data);
        return htmlspecialchars($data, ENT_QUOTES, 'UTF-8');
    }
    public static function getClientIp() {
        $ip = $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
        if (isset($_SERVER['HTTP_X_FORWARDED_FOR'])) $ip = $_SERVER['HTTP_X_FORWARDED_FOR'];
        elseif (isset($_SERVER['HTTP_CLIENT_IP'])) $ip = $_SERVER['HTTP_CLIENT_IP'];
        return filter_var($ip, FILTER_VALIDATE_IP) ? $ip : '0.0.0.0';
    }
}

class Config {
    private static $cache = [];
    public static function get($key, $default = null) {
        if (isset(self::$cache[$key])) return self::$cache[$key];
        $config = [
            'app_name' => APP_NAME,
            'app_url' => APP_URL,
            'base_url' => BASE_URL,
            'app_env' => APP_ENV,
            'app_version' => '2.0.0',
            'timezone' => 'Africa/Lagos',
            'date_format' => 'Y-m-d',
            'datetime_format' => 'Y-m-d H:i:s',
            'session_name' => 'NIS_AMS_SESSION',
            'session_lifetime' => SESSION_LIFETIME,
            'csrf_token_name' => CSRF_TOKEN_NAME,
            'password_min_length' => 8,
            'max_login_attempts' => 5,
            'lockout_time' => 900,
            'max_upload_size' => 10485760,
            'allowed_file_types' => ['pdf', 'jpg', 'jpeg', 'png', 'doc', 'docx'],
            'upload_path' => __DIR__ . '/../assets/uploads/'
        ];
        $value = $config[$key] ?? $default;
        self::$cache[$key] = $value;
        return $value;
    }
}

class Session {
    public static function set($key, $value) { $_SESSION[$key] = $value; }
    public static function get($key, $default = null) { return $_SESSION[$key] ?? $default; }
    public static function has($key) { return isset($_SESSION[$key]); }
    public static function remove($key) { unset($_SESSION[$key]); }
    public static function destroy() {
        $_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();
    }
    public static function regenerate() { session_regenerate_id(true); }
}

class Database {
    private static $pdo = null;
    public static function getInstance() {
        if (self::$pdo === null) self::$pdo = getDBConnection();
        return self::$pdo;
    }
    public static function fetchAll($sql, $params = []) {
        $pdo = self::getInstance();
        if (!$pdo) return [];
        try {
            $stmt = $pdo->prepare($sql);
            $stmt->execute($params);
            return $stmt->fetchAll();
        } catch (Exception $e) { return []; }
    }
    public static function fetchOne($sql, $params = []) {
        $pdo = self::getInstance();
        if (!$pdo) return false;
        try {
            $stmt = $pdo->prepare($sql);
            $stmt->execute($params);
            return $stmt->fetch();
        } catch (Exception $e) { return false; }
    }
    public static function query($sql, $params = []) {
        $pdo = self::getInstance();
        if (!$pdo) return false;
        try {
            $stmt = $pdo->prepare($sql);
            $stmt->execute($params);
            return $stmt;
        } catch (Exception $e) { return false; }
    }
    public static function insert($table, $data) {
        $pdo = self::getInstance();
        if (!$pdo) return false;
        $columns = implode('`, `', array_keys($data));
        $placeholders = implode(', ', array_fill(0, count($data), '?'));
        $sql = "INSERT INTO `$table` (`$columns`) VALUES ($placeholders)";
        try {
            $stmt = $pdo->prepare($sql);
            $stmt->execute(array_values($data));
            return $pdo->lastInsertId();
        } catch (Exception $e) { return false; }
    }
    public static function update($table, $data, $where, $whereParams = []) {
        $pdo = self::getInstance();
        if (!$pdo) return false;
        $set = [];
        foreach (array_keys($data) as $column) $set[] = "`$column` = ?";
        $setClause = implode(', ', $set);
        $sql = "UPDATE `$table` SET $setClause WHERE $where";
        $params = array_merge(array_values($data), $whereParams);
        try {
            $stmt = $pdo->prepare($sql);
            $stmt->execute($params);
            return $stmt->rowCount();
        } catch (Exception $e) { return false; }
    }
    public static function delete($table, $where, $params = []) {
        $pdo = self::getInstance();
        if (!$pdo) return false;
        $sql = "DELETE FROM `$table` WHERE $where";
        try {
            $stmt = $pdo->prepare($sql);
            $stmt->execute($params);
            return $stmt->rowCount();
        } catch (Exception $e) { return false; }
    }
    public static function beginTransaction() { $pdo = self::getInstance(); return $pdo ? $pdo->beginTransaction() : false; }
    public static function commit() { $pdo = self::getInstance(); return $pdo ? $pdo->commit() : false; }
    public static function rollBack() { $pdo = self::getInstance(); return $pdo ? $pdo->rollBack() : false; }
}

// Initialize session
initSession();
?>