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

/**
 * Configuration options for the URL semantic.
 * Controls validation, allowed protocols, and formatting.
 */
export interface URLConfig {
  /**
   * Whether to require HTTPS protocol (default: false).
   * When not set, both HTTP and HTTPS are allowed.
   */
  requireHttps?: boolean
  /**
   * Whether to allow query parameters in the URL.
   */
  allowQueryParams?: boolean
  /**
   * Whether to allow URL fragments (e.g., #section).
   */
  allowFragments?: boolean
  /**
   * Whether to allow internationalized domain names.
   */
  allowInternational?: boolean
  /**
   * Whether to allow IP addresses as hostnames.
   */
  allowIP?: boolean
  /**
   * Whether to allow port numbers in the URL.
   */
  allowPort?: boolean
  /**
   * Whether to allow authentication info (user:pass@host).
   */
  allowAuthentication?: boolean
  /**
   * Custom metadata for the URL field.
   */
  metadata?: Record<string, unknown>
  /**
   * Index signature to allow additional properties.
   */
  [key: string]: unknown
}

/**
 * Type-safe configuration for URL semantic.
 */
export interface AppliedURLSemantic extends AppliedDataSemantic {
  id: SemanticType.URL
  config?: URLConfig
}

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

/**
 * Helper function to create a URL semantic with configuration.
 */
export const createURLSemantic = (config: URLConfig = {}): AppliedURLSemantic => {
  const mergedConfig = {
    ...DEFAULT_URL_CONFIG,
    ...config,
  }
  if (config.metadata) {
    mergedConfig.metadata = { ...config.metadata }
  }

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

/**
 * Default configuration for URL semantic.
 */
export const DEFAULT_URL_CONFIG: URLConfig = {
  requireHttps: false,
  allowQueryParams: true,
  allowFragments: true,
  allowInternational: true,
  allowIP: true,
  allowPort: true,
  allowAuthentication: false,
}
