import type { AppliedDataSemantic } from '../Semantics.js'
import { SemanticType } from '../Semantics.js'

/**
 * Configuration options for the Categories semantic.
 * Controls allowed categories, hierarchy, and formatting for associations.
 */
export interface CategoriesConfig {
  /**
   * List of allowed categories.
   */
  allowedCategories?: string[]
  /**
   * Whether to allow custom categories not in the allowedCategories list.
   */
  allowCustomCategories?: boolean
  /**
   * Whether to allow hierarchical categories (tree structure).
   */
  allowHierarchy?: boolean
  /**
   * Maximum depth of the category hierarchy.
   */
  maxDepth?: number
  /**
   * Whether categories are case sensitive.
   */
  caseSensitive?: boolean
  /**
   * Whether to allow Unicode characters in categories.
   */
  allowUnicode?: boolean
  /**
   * Custom metadata for the categories association.
   */
  metadata?: Record<string, unknown>
  /**
   * Index signature to allow additional properties.
   */
  [key: string]: unknown
}

/**
 * Type-safe configuration for Categories semantic.
 */
export interface AppliedCategoriesSemantic extends AppliedDataSemantic {
  id: SemanticType.Categories
  config?: CategoriesConfig
}

/**
 * Type guard to check if a semantic is a Categories semantic.
 */
export const isCategoriesSemantic = (semantic: AppliedDataSemantic): semantic is AppliedCategoriesSemantic => {
  return semantic.id === SemanticType.Categories
}

/**
 * Helper function to create a Categories semantic with configuration.
 */
export const createCategoriesSemantic = (config: CategoriesConfig = {}): AppliedCategoriesSemantic => {
  const mergedConfig = {
    ...DEFAULT_CATEGORIES_CONFIG,
    ...config,
  }
  if (config.metadata) {
    mergedConfig.metadata = { ...config.metadata }
  }

  return {
    id: SemanticType.Categories,
    config: mergedConfig,
  }
}

/**
 * Default configuration for Categories semantic.
 */
export const DEFAULT_CATEGORIES_CONFIG: CategoriesConfig = {
  allowCustomCategories: true,
  allowHierarchy: true,
  caseSensitive: false,
  allowUnicode: false,
}
