/**
 * Role-based icon control utilities
 *
 * This module provides functions for resolving control visibility and
 * enabled states based on icons_behaviour configuration and active role.
 */
import { DEFAULT_ICON_ORDER, DEFAULT_ROLE_CONTROL_BEHAVIOUR, DEFAULT_ALWAYS_EXTRACTED, DEFAULT_EXTRACTED_ON_VALUE, } from '../../../types/icons_behaviour.js';
/**
 * Get role behaviour for a specific role from icons_behaviour config
 */
export function get_role_behaviour(icons_behaviour, role_id) {
    if (!icons_behaviour?.roles)
        return undefined;
    return icons_behaviour.roles.find(r => r.role_id === role_id);
}
/**
 * Resolve control visibility and editability for a role
 * Returns { visible: boolean, enabled: boolean } for each control
 */
export function resolve_role_controls(icons_behaviour, role_id) {
    const result = {
        control_lock: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_delete: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_visibility: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_data_ok: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_complete: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_skip: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_notes: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_chat: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_add_elements: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_edit_field: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_edit_group: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_delete_field: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_edit_elements: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_private_files: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
        control_revalidate: { ...DEFAULT_ROLE_CONTROL_BEHAVIOUR },
    };
    if (!role_id || !icons_behaviour?.roles)
        return result;
    const role = icons_behaviour.roles.find(r => r.role_id === role_id);
    if (!role)
        return result;
    for (const [control, behaviour] of Object.entries(role.controls)) {
        if (control in result && behaviour) {
            result[control] = {
                visible: behaviour.visible,
                enabled: behaviour.enabled,
                allowed_values: behaviour.allowed_values,
            };
        }
    }
    return result;
}
/**
 * Check if a control has a value/activity (for extraction and border logic)
 *
 * Different controls have different "has value" semantics:
 * - control_data_ok: has value when data_ok is 'ok' or true (approved state)
 * - control_skip: has value when skipped is true (marked as N/A)
 * - control_lock: has value when locked is true
 * - control_delete: has value when deleted is true
 * - control_visibility: has value when visibility is 'hidden'
 * - control_notes: has value when at least one note exists
 * - control_chat: has value when at least one chat message exists
 */
export function control_has_value(control, metadata) {
    if (!metadata)
        return false;
    switch (control) {
        case 'control_data_ok':
            // Has value when data_ok is in the "approved" state (true or 'ok')
            return metadata.data_ok === true || metadata.data_ok === 'ok';
        case 'control_complete':
            return metadata.complete === true;
        case 'control_skip':
            // Has value when field is marked as skipped/N/A
            return metadata.skipped === true;
        case 'control_lock':
            return metadata.locked === true;
        case 'control_delete':
            return metadata.deleted === true;
        case 'control_visibility':
            return metadata.visibility === 'hidden';
        case 'control_notes':
            return (metadata.notes?.length ?? 0) > 0;
        case 'control_chat':
            return (metadata.has_chat_messages === true ||
                metadata.chat_status === 'has_messages' ||
                metadata.chat_status === 'has_unread');
        case 'control_add_elements':
            // Add elements control has no "value" state - it's an action button
            return false;
        case 'control_edit_field':
            // Edit field control has no "value" state - it's an action button
            return false;
        case 'control_edit_group':
            // Edit group control has no "value" state - it's an action button
            return false;
        case 'control_delete_field':
            // Delete field control has no "value" state - it's an action button
            return false;
        case 'control_edit_elements':
            // Edit elements control has no "value" state - it's an action button
            return false;
        case 'control_revalidate':
            // Re-validate control has no "value" state - it's an action button
            return false;
        case 'control_private_files':
            return false;
        default:
            return false;
    }
}
/**
 * Determine if a control should be extracted (shown inline vs in kebab menu)
 *
 * Extraction logic:
 * 1. always_extracted: always extracted (shown inline, never in kebab)
 * 2. extracted_on_value: extracted when has value/activity
 * 3. Default: NOT extracted (will go in kebab if 2+ controls)
 *
 * Note: Data OK (control_data_ok) should always be in always_extracted by default.
 * Controls not extracted will be consolidated into kebab menu if 2+ remain.
 */
export function should_extract_control(control, icons_behaviour, has_value) {
    // No config = all controls inline (legacy behavior)
    if (!icons_behaviour)
        return true;
    // Always extracted takes precedence (use defaults if not specified in config)
    const always_extracted = icons_behaviour.always_extracted ?? DEFAULT_ALWAYS_EXTRACTED;
    if (always_extracted.includes(control))
        return true;
    // Check extracted_on_value - extract when control has value/activity
    // Use defaults if not specified in config (notes and chat extracted when they have values)
    const extracted_on_value = icons_behaviour.extracted_on_value ?? DEFAULT_EXTRACTED_ON_VALUE;
    if (extracted_on_value.includes(control) && has_value)
        return true;
    // Default: not extracted (will be considered for kebab consolidation)
    return false;
}
/**
 * Get the icon order from icons_behaviour or use default
 */
export function get_icon_order(icons_behaviour) {
    return icons_behaviour?.icon_order ?? DEFAULT_ICON_ORDER;
}
/**
 * Determine if a control should have a border based on icons_behaviour config
 *
 * Simple logic:
 * - If icons_behaviour is provided, only controls in border_on have borders
 * - All other controls have no border (default: off)
 * - If icons_behaviour is not provided, fall back to showing borders (legacy behavior)
 *
 * @param control - The control name
 * @param icons_behaviour - The icons behaviour config
 * @param has_value - Unused, kept for API compatibility
 * @returns true if border should be shown
 */
export function should_show_border(control, icons_behaviour, has_value) {
    // No config = legacy behavior (borders on)
    if (!icons_behaviour)
        return true;
    // With config: only controls in border_on have borders, default is off
    return icons_behaviour.border_on?.includes(control) ?? false;
}
/**
 * Check if a control is enabled based on role settings
 * Falls back to individual settings if no role is active
 *
 * IMPORTANT: When fallback_visible is explicitly false (e.g., show_control_icons=false at field level),
 * that takes precedence over role-based settings. This ensures that fields with force-hidden
 * overrides don't display controls even when a role has controls enabled.
 */
export function is_control_visible(control, icons_behaviour, active_role, fallback_visible) {
    // When fallback explicitly says don't show (e.g., show_control_icons=false at field level),
    // respect that regardless of role-based settings
    if (fallback_visible === false) {
        return false;
    }
    if (!active_role || !icons_behaviour?.roles) {
        return fallback_visible;
    }
    const role_controls = resolve_role_controls(icons_behaviour, active_role);
    return role_controls[control].visible;
}
/**
 * Check if a control is enabled (editable/clickable) based on role settings
 * Falls back to individual settings if no role is active
 */
export function is_control_enabled(control, icons_behaviour, active_role, fallback_enabled) {
    if (!active_role || !icons_behaviour?.roles) {
        return fallback_enabled;
    }
    const role_controls = resolve_role_controls(icons_behaviour, active_role);
    return role_controls[control].enabled;
}
/**
 * Get fully resolved control state for a single control
 */
export function resolve_control_state(control, icons_behaviour, active_role, metadata, fallback) {
    const has_value = control_has_value(control, metadata);
    // Get allowed_values from role config if available
    const role_controls = resolve_role_controls(icons_behaviour, active_role);
    const allowed_values = role_controls[control]?.allowed_values;
    return {
        visible: is_control_visible(control, icons_behaviour, active_role, fallback.visible),
        enabled: is_control_enabled(control, icons_behaviour, active_role, fallback.enabled),
        extracted: should_extract_control(control, icons_behaviour, has_value),
        show_border: should_show_border(control, icons_behaviour, has_value),
        allowed_values,
    };
}
/**
 * Resolve private file access permission based on role settings
 *
 * Returns true if the active role has `control_private_files.visible: true` in their controls.
 * This is used to control visibility of private file sections at the form level,
 * instead of per-field configuration.
 *
 * @param icons_behaviour - The icons behaviour / global settings config
 * @param role_id - The active role ID to check
 * @returns true if the role can access private files, false otherwise
 */
export function can_role_access_private_files(icons_behaviour, role_id) {
    if (!icons_behaviour?.roles || !role_id)
        return false;
    const role = icons_behaviour.roles.find(r => r.role_id === role_id);
    return role?.controls?.control_private_files?.visible ?? false;
}
//# sourceMappingURL=role_utils.js.map