// #region AdminService [C:3] [TYPE Service] [SEMANTICS admin, service, user, role, rbac]
// @BRIEF Service for Admin-related API calls including User and Role management, AD group mappings, and logging configuration.
// @LAYER Service
// @RELATION DEPENDS_ON -> [ApiModule]

// #region adminService:Module [TYPE Function]
//
// @SEMANTICS: admin, users, roles, ad-mappings, api
// @PURPOSE:   Service for Admin-related API calls (User and Role management).
// @LAYER     Service
// @RELATION  DEPENDS_ON -> [EXT:frontend:api_module]
//
// @INVARIANT: All requests must include valid Admin JWT token (handled by api client).

// [SECTION: IMPORTS]
import { api } from '../lib/api';
import { log } from '$lib/cot-logger';
// [/SECTION]

interface UserData {
  username?: string;
  email?: string;
  password?: string;
  roles?: string[];
  is_active?: boolean;
  [key: string]: unknown;
}

interface RoleData {
  name?: string;
  description?: string;
  permissions?: string[];
  [key: string]: unknown;
}

interface ADGroupMappingData {
  ad_group?: string;
  role_id?: string;
  [key: string]: unknown;
}

interface LoggingConfigData {
  level?: string;
  task_log_level?: string;
  enable_belief_state?: boolean;
  [key: string]: unknown;
}

// #region getUsers:Function [TYPE Function]
/**
 * @purpose Fetches all registered users from the backend.
 * @pre     User must be authenticated with Admin privileges.
 * @post    Returns an array of user objects.
 * @returns Array of user objects.
 * @relation CALLS -> [EXT:path:backend.src.api.routes.admin.list_users]
 */
async function getUsers<T = unknown>(): Promise<T> {
    log("adminService", "REASON", "Fetching users");
    try {
        const users = await api.requestApi<T>('/admin/users', 'GET');
        log("adminService", "REFLECT", "Users fetched successfully");
        return users;
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to fetch users", {}, String(e));
        throw e;
    }
}
// #endregion getUsers:Function

// #region createUser:Function [TYPE Function]
/**
 * @purpose Creates a new local user.
 * @pre     User must be authenticated with Admin privileges.
 * @param   userData - User details (username, email, password, roles, is_active).
 * @post    New user record created in auth.db.
 * @returns New user object.
 * @relation CALLS -> [EXT:path:backend.src.api.routes.admin.create_user]
 */
async function createUser<T = unknown>(userData: UserData): Promise<T> {
    log("adminService", "REASON", "Creating user", { username: userData?.username });
    try {
        const user = await api.postApi<T>('/admin/users', userData);
        log("adminService", "REFLECT", "User created successfully");
        return user;
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to create user", {}, String(e));
        throw e;
    }
}
// #endregion createUser:Function

// #region getRoles:Function [TYPE Function]
/**
 * @purpose Fetches all available system roles.
 * @pre User must be authenticated with Admin privileges.
 * @post Returns an array of role objects.
 * @returns Array of role objects.
 * @relation CALLS -> [EXT:path:backend.src.api.routes.admin.list_roles]
 */
async function getRoles<T = unknown>(): Promise<T> {
    log("adminService", "REASON", "Fetching roles");
    try {
        const roles = await api.requestApi<T>('/admin/roles', 'GET');
        log("adminService", "REFLECT", "Roles fetched successfully");
        return roles;
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to fetch roles", {}, String(e));
        throw e;
    }
}
// #endregion getRoles:Function

// #region getADGroupMappings:Function [TYPE Function]
/**
 * @purpose Fetches mappings between AD groups and local roles.
 * @pre User must be authenticated with Admin privileges.
 * @post Returns an array of AD group mapping objects.
 * @returns Array of AD group mapping objects.
 */
async function getADGroupMappings<T = unknown>(): Promise<T> {
    log("adminService", "REASON", "Fetching AD group mappings");
    try {
        const mappings = await api.requestApi<T>('/admin/ad-mappings', 'GET');
        log("adminService", "REFLECT", "AD group mappings fetched successfully");
        return mappings;
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to fetch AD group mappings", {}, String(e));
        throw e;
    }
}
// #endregion getADGroupMappings:Function

// #region createADGroupMapping:Function [TYPE Function]
/**
 * @purpose Creates or updates an AD group to Role mapping.
 * @pre User must be authenticated with Admin privileges.
 * @post New or updated mapping created in auth.db.
 * @param   mappingData - Mapping details (ad_group, role_id).
 * @returns New mapping object.
 */
async function createADGroupMapping<T = unknown>(mappingData: ADGroupMappingData): Promise<T> {
    log("adminService", "REASON", "Creating AD group mapping");
    try {
        const mapping = await api.postApi<T>('/admin/ad-mappings', mappingData);
        log("adminService", "REFLECT", "AD group mapping created successfully");
        return mapping;
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to create AD group mapping", {}, String(e));
        throw e;
    }
}
// #endregion createADGroupMapping:Function

// #region updateUser:Function [TYPE Function]
/**
 * @purpose Updates an existing user.
 * @pre     User must be authenticated with Admin privileges.
 * @post    User record updated in auth.db.
 * @param   userId - Target user ID.
 * @param   userData - Updated user data.
 * @returns Updated user object.
 */
async function updateUser<T = unknown>(userId: string, userData: UserData): Promise<T> {
    log("adminService", "REASON", "Updating user", { userId });
    try {
        const user = await api.requestApi<T>(`/admin/users/${userId}`, 'PUT', userData);
        log("adminService", "REFLECT", "User updated successfully");
        return user;
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to update user", { userId }, String(e));
        throw e;
    }
}
// #endregion updateUser:Function

// #region deleteUser:Function [TYPE Function]
/**
 * @purpose Deletes a user.
 * @pre     User must be authenticated with Admin privileges.
 * @post    User record removed from auth.db.
 * @param   userId - Target user ID.
 * @returns Promise that resolves when deletion is complete.
 */
async function deleteUser(userId: string): Promise<void> {
    log("adminService", "REASON", "Deleting user", { userId });
    try {
        await api.requestApi(`/admin/users/${userId}`, 'DELETE');
        log("adminService", "REFLECT", "User deleted successfully");
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to delete user", { userId }, String(e));
        throw e;
    }
}
// #endregion deleteUser:Function

// #region createRole:Function [TYPE Function]
/**
 * @purpose Creates a new role.
 * @pre     User must be authenticated with Admin privileges.
 * @post    New role created in auth.db.
 * @param   roleData - Role details (name, description, permissions).
 * @returns New role object.
 */
async function createRole<T = unknown>(roleData: RoleData): Promise<T> {
    log("adminService", "REASON", "Creating role");
    try {
        const role = await api.postApi<T>('/admin/roles', roleData);
        log("adminService", "REFLECT", "Role created successfully");
        return role;
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to create role", {}, String(e));
        throw e;
    }
}
// #endregion createRole:Function

// #region updateRole:Function [TYPE Function]
/**
 * @purpose Updates an existing role.
 * @param   roleId - Target role ID.
 * @param   roleData - Updated role data.
 * @returns Updated role object.
 */
async function updateRole<T = unknown>(roleId: string, roleData: RoleData): Promise<T> {
    log("adminService", "REASON", "Updating role", { roleId });
    try {
        const role = await api.requestApi<T>(`/admin/roles/${roleId}`, 'PUT', roleData);
        log("adminService", "REFLECT", "Role updated successfully");
        return role;
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to update role", { roleId }, String(e));
        throw e;
    }
}
// #endregion updateRole:Function

// #region deleteRole:Function [TYPE Function]
/**
 * @purpose Deletes a role.
 * @param   roleId - Target role ID.
 * @returns Promise that resolves when deletion is complete.
 */
async function deleteRole(roleId: string): Promise<void> {
    log("adminService", "REASON", "Deleting role", { roleId });
    try {
        await api.requestApi(`/admin/roles/${roleId}`, 'DELETE');
        log("adminService", "REFLECT", "Role deleted successfully");
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to delete role", { roleId }, String(e));
        throw e;
    }
}
// #endregion deleteRole:Function

// #region getPermissions:Function [TYPE Function]
/**
 * @purpose Fetches all available permissions.
 * @returns Array of permission objects.
 */
async function getPermissions<T = unknown>(): Promise<T> {
    log("adminService", "REASON", "Fetching permissions");
    try {
        const permissions = await api.requestApi<T>('/admin/permissions', 'GET');
        log("adminService", "REFLECT", "Permissions fetched successfully");
        return permissions;
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to fetch permissions", {}, String(e));
        throw e;
    }
}
// #endregion getPermissions:Function

// #region getLoggingConfig:Function [TYPE Function]
/**
 * @purpose Fetches current logging configuration.
 * @returns Logging config with level, task_log_level, enable_belief_state.
 * @relation CALLS -> [EXT:path:backend.src.api.routes.settings.get_logging_config]
 */
async function getLoggingConfig<T = unknown>(): Promise<T> {
    log("adminService", "REASON", "Fetching logging config");
    try {
        const config = await api.requestApi<T>('/settings/logging', 'GET');
        log("adminService", "REFLECT", "Logging config fetched successfully");
        return config;
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to fetch logging config", {}, String(e));
        throw e;
    }
}
// #endregion getLoggingConfig:Function

// #region updateLoggingConfig:Function [TYPE Function]
/**
 * @purpose Updates logging configuration.
 * @param   configData - Logging config (level, task_log_level, enable_belief_state).
 * @returns Updated logging config.
 * @relation CALLS -> [EXT:path:backend.src.api.routes.settings.update_logging_config]
 */
async function updateLoggingConfig<T = unknown>(configData: LoggingConfigData): Promise<T> {
    log("adminService", "REASON", "Updating logging config");
    try {
        const config = await api.requestApi<T>('/settings/logging', 'PATCH', configData);
        log("adminService", "REFLECT", "Logging config updated successfully");
        return config;
    } catch (e) {
        log("adminService", "EXPLORE", "Failed to update logging config", {}, String(e));
        throw e;
    }
}
// #endregion updateLoggingConfig:Function

export const adminService = {
    getUsers,
    createUser,
    updateUser,
    deleteUser,
    getRoles,
    createRole,
    updateRole,
    deleteRole,
    getPermissions,
    getADGroupMappings,
    createADGroupMapping,
    getLoggingConfig,
    updateLoggingConfig
};

// #endregion adminService:Module
// #endregion AdminService
