import {
  type WizardConfig,
  type WizardStep,
  type WizardFieldConfig,
  type WizardStepId,
  DEFAULT_WIZARD_CONFIG,
  wizardConfigSchema,
} from '@/types/wizard-config'

/**
 * Parse wizard config from Program.settingsJson with fallback to defaults.
 * Used by both backend (application router) and frontend (apply pages).
 */
export function parseWizardConfig(settingsJson: unknown): WizardConfig {
  if (!settingsJson || typeof settingsJson !== 'object') {
    return DEFAULT_WIZARD_CONFIG
  }
  const settings = settingsJson as Record<string, unknown>
  if (!settings.wizardConfig) {
    return DEFAULT_WIZARD_CONFIG
  }
  try {
    const parsed = wizardConfigSchema.parse(settings.wizardConfig)
    return mergeWizardConfig(parsed)
  } catch {
    console.error('[WizardConfig] Invalid config, using defaults')
    return DEFAULT_WIZARD_CONFIG
  }
}

/**
 * Get enabled steps sorted by order.
 */
export function getActiveSteps(config: WizardConfig): WizardStep[] {
  return config.steps.filter((step) => step.enabled).sort((a, b) => a.order - b.order)
}

/**
 * Evaluate conditional step visibility based on current form values.
 * Returns only steps whose conditions are met (or have no condition).
 */
export function getVisibleSteps(
  config: WizardConfig,
  formValues: Record<string, unknown>
): WizardStep[] {
  return getActiveSteps(config).filter((step) => {
    if (!step.conditionalOn) return true
    const { field, operator, value } = step.conditionalOn
    const fieldValue = formValues[field]
    switch (operator) {
      case 'equals':
        return fieldValue === value
      case 'notEquals':
        return fieldValue !== value
      case 'in':
        return Array.isArray(value) && value.includes(String(fieldValue))
      case 'notIn':
        return Array.isArray(value) && !value.includes(String(fieldValue))
      default:
        return true
    }
  })
}

/**
 * Get field configuration with sensible defaults.
 */
export function getFieldConfig(config: WizardConfig, fieldName: string): WizardFieldConfig {
  return config.fields[fieldName] ?? { required: true, visible: true }
}

/**
 * Check if a specific field should be visible based on config.
 */
export function isFieldVisible(config: WizardConfig, fieldName: string): boolean {
  const fieldConfig = config.fields[fieldName]
  return fieldConfig?.visible !== false
}

/**
 * Check if a specific field is required based on config.
 */
export function isFieldRequired(config: WizardConfig, fieldName: string): boolean {
  const fieldConfig = config.fields[fieldName]
  return fieldConfig?.required !== false
}

/**
 * Get custom fields assigned to a specific step, sorted by order.
 */
export function getCustomFieldsForStep(
  config: WizardConfig,
  stepId: WizardStepId
): NonNullable<WizardConfig['customFields']> {
  return (config.customFields ?? [])
    .filter((f) => f.stepId === stepId)
    .sort((a, b) => a.order - b.order)
}

/**
 * Merge partial config with defaults. Ensures all arrays/objects exist.
 */
export function mergeWizardConfig(partial: Partial<WizardConfig>): WizardConfig {
  return {
    steps: partial.steps?.length ? partial.steps : DEFAULT_WIZARD_CONFIG.steps,
    fields: partial.fields ?? DEFAULT_WIZARD_CONFIG.fields,
    competitionCategories:
      partial.competitionCategories ?? DEFAULT_WIZARD_CONFIG.competitionCategories,
    oceanIssues: partial.oceanIssues ?? DEFAULT_WIZARD_CONFIG.oceanIssues,
    features: { ...DEFAULT_WIZARD_CONFIG.features, ...partial.features },
    welcomeMessage: partial.welcomeMessage,
    customFields: partial.customFields ?? [],
  }
}

/**
 * Build the STEPS array for the wizard from config (format used by apply pages).
 * Maps step IDs to their validation fields for per-step validation.
 */
export function buildStepsArray(
  config: WizardConfig
): Array<{ id: string; title: string; fields: string[] }> {
  const STEP_FIELDS_MAP: Record<string, string[]> = {
    welcome: ['competitionCategory'],
    contact: ['contactName', 'contactEmail', 'contactPhone', 'country'],
    project: ['projectName', 'description', 'oceanIssue'],
    team: [],
    additional: [],
    review: ['gdprConsent'],
  }

  return getActiveSteps(config).map((step) => ({
    id: step.id,
    title: step.title ?? step.id.charAt(0).toUpperCase() + step.id.slice(1),
    fields: (STEP_FIELDS_MAP[step.id] ?? []).filter((f) => isFieldVisible(config, f)),
  }))
}
