<?php
/**
 * Configuration File - COMPLETE WORKING VERSION WITH ROLE-BASED PERMISSIONS
 */

// =============================================
// 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', 'stbenedi_ams');
define('DB_USER', 'stbenedi_ams');
define('DB_PASS', 'H9GMpL1RydC');
define('DB_CHARSET', 'utf8mb4');

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

define('APP_NAME', 'NIS Asset Management System');
define('APP_URL', 'https://niscoreapps.com.ng/nis_ams');
define('BASE_URL', APP_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 - WITH ROLE-BASED ACCESS
 */
function hasPermission($permission) {
    if (!isLoggedIn()) return false;
    
    // Super Admin can do everything
    if (hasRole('Super Admin Officer')) return true;
    
    // Armourer permissions for weapons management
    if (hasRole('Armourer')) {
        $weaponPermissions = [
            'weapons.view', 'weapons.create', 'weapons.edit', 'weapons.delete',
            'ammunition.view', 'ammunition.create', 'ammunition.edit', 'ammunition.delete',
            'requisition.view', 'requisition.create', 'requisition.edit', 'requisition.delete', 'requisition.approve',
            'returns.view', 'returns.create', 'returns.edit', 'returns.delete',
            'weapon_issue.view', 'weapon_issue.create', 'weapon_issue.edit', 'weapon_issue.delete',
            'audit.view', 'audit.create', 'audit.edit', 'audit.delete'
        ];
        if (in_array($permission, $weaponPermissions)) return true;
    }
    
    // Command Armourer, Command Approval Officer, HQ Vetting Officer - only requisition
    if (hasRole('Command Armourer') || hasRole('Command Approval Officer') || hasRole('HQ Vetting Officer')) {
        $requisitionPermissions = [
            'requisition.view', 'requisition.create', 'requisition.edit', 'requisition.approve'
        ];
        if (in_array($permission, $requisitionPermissions)) return true;
    }
    
    // Sectional Head Transport - fleet permissions
    if (hasRole('Sectional Head Transport')) {
        $fleetPermissions = [
            'fleet.view', 'fleet.create', 'fleet.edit', 'fleet.delete',
            'vehicles.view', 'vehicles.create', 'vehicles.edit', 'vehicles.delete',
            'aircraft.view', 'aircraft.create', 'aircraft.edit', 'aircraft.delete',
            'marine.view', 'marine.create', 'marine.edit', 'marine.delete',
            'motorcycles.view', 'motorcycles.create', 'motorcycles.edit', 'motorcycles.delete'
        ];
        if (in_array($permission, $fleetPermissions)) return true;
    }
    
    // Sectional Head ICT - ICT permissions
    if (hasRole('Sectional Head ICT')) {
        $ictPermissions = [
            'ict.view', 'ict.create', 'ict.edit', 'ict.delete'
        ];
        if (in_array($permission, $ictPermissions)) return true;
    }
    
    // Regular permission check from database
    $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); }
    
    // Role helper methods
    public static function isSuperAdmin() { return hasRole('Super Admin Officer'); }
    public static function isArmourer() { return hasRole('Armourer'); }
    public static function isCommandArmourer() { return hasRole('Command Armourer'); }
    public static function isCommandApprovalOfficer() { return hasRole('Command Approval Officer'); }
    public static function isHQVettingOfficer() { return hasRole('HQ Vetting Officer'); }
    public static function isSectionalHeadTransport() { return hasRole('Sectional Head Transport'); }
    public static function isSectionalHeadICT() { return hasRole('Sectional Head ICT'); }
    public static function isCommandDataEntryOfficer() { return hasRole('Command Data Entry Officer'); }
    public static function isHQSectionalSupervisor() { return hasRole('HQ Sectional Supervisor'); }
    
    public static function can($permission) { return hasPermission($permission); }
    
    public static function canAny($permissions) {
        if (!isLoggedIn()) return false;
        if (self::isSuperAdmin()) return true;
        foreach ($permissions as $permission) {
            if (self::can($permission)) 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) {
            error_log("Database::insert - No database connection");
            return false;
        }
        
        if (empty($data)) {
            error_log("Database::insert - No data provided for table: " . $table);
            return false;
        }
        
        $columns = array_keys($data);
        $placeholders = array_fill(0, count($data), '?');
        $sql = "INSERT INTO `$table` (`" . implode('`, `', $columns) . "`) VALUES (" . implode(', ', $placeholders) . ")";
        
        error_log("Database::insert SQL for $table: " . $sql);
        error_log("Database::insert Data for $table: " . print_r(array_values($data), true));
        
        try {
            $stmt = $pdo->prepare($sql);
            $result = $stmt->execute(array_values($data));
            
            if ($result) {
                $lastId = $pdo->lastInsertId();
                error_log("Database::insert Success for $table - ID: " . $lastId);
                return $lastId;
            } else {
                error_log("Database::insert Failed for $table - Execute returned false");
                error_log("PDO Error Info: " . print_r($stmt->errorInfo(), true));
                return false;
            }
        } catch (Exception $e) {
            error_log("Database::insert Exception for $table: " . $e->getMessage());
            error_log("Stack trace: " . $e->getTraceAsString());
            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();