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

/**
 * Supported encryption algorithms for password hashing.
 */
export enum PasswordEncryptionAlgorithm {
  /**
   * bcrypt - Industry standard, secure, and widely supported
   */
  Bcrypt = 'bcrypt',
  /**
   * Argon2 - Winner of the Password Hashing Competition, very secure
   */
  Argon2 = 'argon2',
  /**
   * scrypt - Memory-hard function, good for high-security applications
   */
  Scrypt = 'scrypt',
}

/**
 * Configuration options for the Password semantic.
 * These options control password validation and encryption behavior.
 */
export interface PasswordConfig {
  /**
   * Whether to require special characters.
   * Defaults to false if not specified.
   */
  requireSpecialChars?: boolean

  /**
   * Whether to require numbers.
   * Defaults to false if not specified.
   */
  requireNumbers?: boolean

  /**
   * Whether to require uppercase letters.
   * Defaults to false if not specified.
   */
  requireUppercase?: boolean

  /**
   * Whether to require lowercase letters.
   * Defaults to false if not specified.
   */
  requireLowercase?: boolean

  /**
   * Encryption algorithm to use for password hashing.
   * Defaults to 'bcrypt' if not specified.
   */
  encryptionAlgorithm?: PasswordEncryptionAlgorithm

  /**
   * Number of salt rounds for bcrypt.
   * Defaults to 12 if not specified.
   */
  saltRounds?: number

  /**
   * Maximum age of password in days before requiring change.
   * Defaults to null (no expiration) if not specified.
   */
  maxAge?: number

  /**
   * Whether to prevent reuse of recent passwords.
   * Defaults to false if not specified.
   */
  preventReuse?: boolean

  /**
   * Number of recent passwords to prevent reuse.
   * Defaults to 5 if preventReuse is true.
   */
  preventReuseCount?: number

  /**
   * Custom password validation regex pattern.
   * If specified, overrides other validation rules.
   */
  customPattern?: string

  /**
   * Custom error message for validation failures.
   */
  customErrorMessage?: string

  /**
   * Whether to allow common passwords.
   * Defaults to false if not specified.
   */
  allowCommonPasswords?: boolean

  /**
   * Custom metadata for the password field.
   */
  metadata?: Record<string, unknown>

  /**
   * Index signature to allow additional properties.
   */
  [key: string]: unknown
}

/**
 * Type-safe configuration for Password semantic.
 */
export interface AppliedPasswordSemantic extends AppliedDataSemantic {
  id: SemanticType.Password
  config?: PasswordConfig
}

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

/**
 * Helper function to create a Password semantic with configuration.
 */
export const createPasswordSemantic = (config: PasswordConfig = {}): AppliedPasswordSemantic => {
  const mergedConfig = {
    ...DEFAULT_PASSWORD_CONFIG,
    ...config,
  }
  if (config.metadata) {
    mergedConfig.metadata = { ...config.metadata }
  }

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

/**
 * Default configuration for Password semantic.
 */
export const DEFAULT_PASSWORD_CONFIG: PasswordConfig = {
  requireSpecialChars: true,
  requireNumbers: true,
  requireUppercase: true,
  requireLowercase: true,
  minLength: 8,
  preventReuse: false,
  preventReuseCount: 5,
  allowCommonPasswords: false,
}
