import { type AnimationLevel } from '../../utils/animationLevel'

export type FeedbackCueKey =
  | 'session_started'
  | 'session_finished'
  | 'hint:changed'
  | 'control_completed:start'
  | 'control_completed:control'
  | 'control_completed:finish'
  | 'punch_feedback:warning'
  | 'guidance:searching'
  | 'guidance:distant'
  | 'guidance:approaching'
  | 'guidance:ready'

export type HapticPattern = 'short' | 'long'
export type UiPunchFeedbackMotion = 'none' | 'pop' | 'success' | 'warning'
export type UiContentCardMotion = 'none' | 'pop' | 'finish'
export type UiPunchButtonMotion = 'none' | 'ready' | 'warning'
export type UiMapPulseMotion = 'none' | 'ready' | 'control' | 'finish'
export type UiStageMotion = 'none' | 'control' | 'finish'
export type UiHudProgressMotion = 'none' | 'success' | 'finish'
export type UiHudDistanceMotion = 'none' | 'success'

export interface HapticCueConfig {
  enabled: boolean
  pattern: HapticPattern
}

export interface UiCueConfig {
  enabled: boolean
  punchFeedbackMotion: UiPunchFeedbackMotion
  contentCardMotion: UiContentCardMotion
  punchButtonMotion: UiPunchButtonMotion
  mapPulseMotion: UiMapPulseMotion
  stageMotion: UiStageMotion
  hudProgressMotion: UiHudProgressMotion
  hudDistanceMotion: UiHudDistanceMotion
  durationMs: number
}

export interface GameHapticsConfig {
  enabled: boolean
  cues: Record<FeedbackCueKey, HapticCueConfig>
}

export interface GameUiEffectsConfig {
  enabled: boolean
  cues: Record<FeedbackCueKey, UiCueConfig>
}

export interface ResolvedGameUiEffectsConfig extends GameUiEffectsConfig {
  animationLevel: AnimationLevel
}

export interface PartialHapticCueConfig {
  enabled?: boolean
  pattern?: HapticPattern
}

export interface PartialUiCueConfig {
  enabled?: boolean
  punchFeedbackMotion?: UiPunchFeedbackMotion
  contentCardMotion?: UiContentCardMotion
  punchButtonMotion?: UiPunchButtonMotion
  mapPulseMotion?: UiMapPulseMotion
  stageMotion?: UiStageMotion
  hudProgressMotion?: UiHudProgressMotion
  hudDistanceMotion?: UiHudDistanceMotion
  durationMs?: number
}

export interface GameHapticsConfigOverrides {
  enabled?: boolean
  cues?: Partial<Record<FeedbackCueKey, PartialHapticCueConfig>>
}

export interface GameUiEffectsConfigOverrides {
  enabled?: boolean
  cues?: Partial<Record<FeedbackCueKey, PartialUiCueConfig>>
}

export const DEFAULT_GAME_HAPTICS_CONFIG: GameHapticsConfig = {
  enabled: true,
  cues: {
    session_started: { enabled: false, pattern: 'short' },
    session_finished: { enabled: true, pattern: 'long' },
    'hint:changed': { enabled: true, pattern: 'short' },
    'control_completed:start': { enabled: true, pattern: 'short' },
    'control_completed:control': { enabled: true, pattern: 'short' },
    'control_completed:finish': { enabled: true, pattern: 'long' },
    'punch_feedback:warning': { enabled: true, pattern: 'short' },
    'guidance:searching': { enabled: false, pattern: 'short' },
    'guidance:distant': { enabled: true, pattern: 'short' },
    'guidance:approaching': { enabled: true, pattern: 'short' },
    'guidance:ready': { enabled: true, pattern: 'short' },
  },
}

export const DEFAULT_GAME_UI_EFFECTS_CONFIG: GameUiEffectsConfig = {
  enabled: true,
  cues: {
    session_started: { enabled: false, punchFeedbackMotion: 'none', contentCardMotion: 'none', punchButtonMotion: 'none', mapPulseMotion: 'none', stageMotion: 'none', hudProgressMotion: 'none', hudDistanceMotion: 'none', durationMs: 0 },
    session_finished: { enabled: false, punchFeedbackMotion: 'none', contentCardMotion: 'none', punchButtonMotion: 'none', mapPulseMotion: 'none', stageMotion: 'none', hudProgressMotion: 'none', hudDistanceMotion: 'none', durationMs: 0 },
    'hint:changed': { enabled: false, punchFeedbackMotion: 'none', contentCardMotion: 'none', punchButtonMotion: 'none', mapPulseMotion: 'none', stageMotion: 'none', hudProgressMotion: 'none', hudDistanceMotion: 'none', durationMs: 0 },
    'control_completed:start': { enabled: true, punchFeedbackMotion: 'success', contentCardMotion: 'pop', punchButtonMotion: 'none', mapPulseMotion: 'control', stageMotion: 'control', hudProgressMotion: 'success', hudDistanceMotion: 'success', durationMs: 560 },
    'control_completed:control': { enabled: true, punchFeedbackMotion: 'success', contentCardMotion: 'pop', punchButtonMotion: 'none', mapPulseMotion: 'control', stageMotion: 'control', hudProgressMotion: 'success', hudDistanceMotion: 'success', durationMs: 560 },
    'control_completed:finish': { enabled: true, punchFeedbackMotion: 'success', contentCardMotion: 'finish', punchButtonMotion: 'none', mapPulseMotion: 'finish', stageMotion: 'finish', hudProgressMotion: 'finish', hudDistanceMotion: 'success', durationMs: 680 },
    'punch_feedback:warning': { enabled: true, punchFeedbackMotion: 'warning', contentCardMotion: 'none', punchButtonMotion: 'warning', mapPulseMotion: 'none', stageMotion: 'none', hudProgressMotion: 'none', hudDistanceMotion: 'none', durationMs: 560 },
    'guidance:searching': { enabled: false, punchFeedbackMotion: 'none', contentCardMotion: 'none', punchButtonMotion: 'none', mapPulseMotion: 'none', stageMotion: 'none', hudProgressMotion: 'none', hudDistanceMotion: 'none', durationMs: 0 },
    'guidance:distant': { enabled: false, punchFeedbackMotion: 'none', contentCardMotion: 'none', punchButtonMotion: 'none', mapPulseMotion: 'none', stageMotion: 'none', hudProgressMotion: 'none', hudDistanceMotion: 'none', durationMs: 0 },
    'guidance:approaching': { enabled: false, punchFeedbackMotion: 'none', contentCardMotion: 'none', punchButtonMotion: 'none', mapPulseMotion: 'none', stageMotion: 'none', hudProgressMotion: 'none', hudDistanceMotion: 'none', durationMs: 0 },
    'guidance:ready': { enabled: true, punchFeedbackMotion: 'none', contentCardMotion: 'none', punchButtonMotion: 'ready', mapPulseMotion: 'ready', stageMotion: 'none', hudProgressMotion: 'none', hudDistanceMotion: 'none', durationMs: 900 },
  },
}

function clampDuration(value: number, fallback: number): number {
  return Number.isFinite(value) && value >= 0 ? value : fallback
}

function mergeHapticCue(baseCue: HapticCueConfig, override?: PartialHapticCueConfig): HapticCueConfig {
  return {
    enabled: override && override.enabled !== undefined ? !!override.enabled : baseCue.enabled,
    pattern: override && override.pattern ? override.pattern : baseCue.pattern,
  }
}

function mergeUiCue(baseCue: UiCueConfig, override?: PartialUiCueConfig): UiCueConfig {
  return {
    enabled: override && override.enabled !== undefined ? !!override.enabled : baseCue.enabled,
    punchFeedbackMotion: override && override.punchFeedbackMotion ? override.punchFeedbackMotion : baseCue.punchFeedbackMotion,
    contentCardMotion: override && override.contentCardMotion ? override.contentCardMotion : baseCue.contentCardMotion,
    punchButtonMotion: override && override.punchButtonMotion ? override.punchButtonMotion : baseCue.punchButtonMotion,
    mapPulseMotion: override && override.mapPulseMotion ? override.mapPulseMotion : baseCue.mapPulseMotion,
    stageMotion: override && override.stageMotion ? override.stageMotion : baseCue.stageMotion,
    hudProgressMotion: override && override.hudProgressMotion ? override.hudProgressMotion : baseCue.hudProgressMotion,
    hudDistanceMotion: override && override.hudDistanceMotion ? override.hudDistanceMotion : baseCue.hudDistanceMotion,
    durationMs: clampDuration(Number(override && override.durationMs), baseCue.durationMs),
  }
}

export function mergeGameHapticsConfig(overrides?: GameHapticsConfigOverrides | null): GameHapticsConfig {
  const cues: GameHapticsConfig['cues'] = {
    session_started: mergeHapticCue(DEFAULT_GAME_HAPTICS_CONFIG.cues.session_started, overrides && overrides.cues ? overrides.cues.session_started : undefined),
    session_finished: mergeHapticCue(DEFAULT_GAME_HAPTICS_CONFIG.cues.session_finished, overrides && overrides.cues ? overrides.cues.session_finished : undefined),
    'hint:changed': mergeHapticCue(DEFAULT_GAME_HAPTICS_CONFIG.cues['hint:changed'], overrides && overrides.cues ? overrides.cues['hint:changed'] : undefined),
    'control_completed:start': mergeHapticCue(DEFAULT_GAME_HAPTICS_CONFIG.cues['control_completed:start'], overrides && overrides.cues ? overrides.cues['control_completed:start'] : undefined),
    'control_completed:control': mergeHapticCue(DEFAULT_GAME_HAPTICS_CONFIG.cues['control_completed:control'], overrides && overrides.cues ? overrides.cues['control_completed:control'] : undefined),
    'control_completed:finish': mergeHapticCue(DEFAULT_GAME_HAPTICS_CONFIG.cues['control_completed:finish'], overrides && overrides.cues ? overrides.cues['control_completed:finish'] : undefined),
    'punch_feedback:warning': mergeHapticCue(DEFAULT_GAME_HAPTICS_CONFIG.cues['punch_feedback:warning'], overrides && overrides.cues ? overrides.cues['punch_feedback:warning'] : undefined),
    'guidance:searching': mergeHapticCue(DEFAULT_GAME_HAPTICS_CONFIG.cues['guidance:searching'], overrides && overrides.cues ? overrides.cues['guidance:searching'] : undefined),
    'guidance:distant': mergeHapticCue(DEFAULT_GAME_HAPTICS_CONFIG.cues['guidance:distant'], overrides && overrides.cues ? overrides.cues['guidance:distant'] : undefined),
    'guidance:approaching': mergeHapticCue(DEFAULT_GAME_HAPTICS_CONFIG.cues['guidance:approaching'], overrides && overrides.cues ? overrides.cues['guidance:approaching'] : undefined),
    'guidance:ready': mergeHapticCue(DEFAULT_GAME_HAPTICS_CONFIG.cues['guidance:ready'], overrides && overrides.cues ? overrides.cues['guidance:ready'] : undefined),
  }

  return {
    enabled: overrides && overrides.enabled !== undefined ? !!overrides.enabled : DEFAULT_GAME_HAPTICS_CONFIG.enabled,
    cues,
  }
}

export function mergeGameUiEffectsConfig(overrides?: GameUiEffectsConfigOverrides | null): GameUiEffectsConfig {
  const cues: GameUiEffectsConfig['cues'] = {
    session_started: mergeUiCue(DEFAULT_GAME_UI_EFFECTS_CONFIG.cues.session_started, overrides && overrides.cues ? overrides.cues.session_started : undefined),
    session_finished: mergeUiCue(DEFAULT_GAME_UI_EFFECTS_CONFIG.cues.session_finished, overrides && overrides.cues ? overrides.cues.session_finished : undefined),
    'hint:changed': mergeUiCue(DEFAULT_GAME_UI_EFFECTS_CONFIG.cues['hint:changed'], overrides && overrides.cues ? overrides.cues['hint:changed'] : undefined),
    'control_completed:start': mergeUiCue(DEFAULT_GAME_UI_EFFECTS_CONFIG.cues['control_completed:start'], overrides && overrides.cues ? overrides.cues['control_completed:start'] : undefined),
    'control_completed:control': mergeUiCue(DEFAULT_GAME_UI_EFFECTS_CONFIG.cues['control_completed:control'], overrides && overrides.cues ? overrides.cues['control_completed:control'] : undefined),
    'control_completed:finish': mergeUiCue(DEFAULT_GAME_UI_EFFECTS_CONFIG.cues['control_completed:finish'], overrides && overrides.cues ? overrides.cues['control_completed:finish'] : undefined),
    'punch_feedback:warning': mergeUiCue(DEFAULT_GAME_UI_EFFECTS_CONFIG.cues['punch_feedback:warning'], overrides && overrides.cues ? overrides.cues['punch_feedback:warning'] : undefined),
    'guidance:searching': mergeUiCue(DEFAULT_GAME_UI_EFFECTS_CONFIG.cues['guidance:searching'], overrides && overrides.cues ? overrides.cues['guidance:searching'] : undefined),
    'guidance:distant': mergeUiCue(DEFAULT_GAME_UI_EFFECTS_CONFIG.cues['guidance:distant'], overrides && overrides.cues ? overrides.cues['guidance:distant'] : undefined),
    'guidance:approaching': mergeUiCue(DEFAULT_GAME_UI_EFFECTS_CONFIG.cues['guidance:approaching'], overrides && overrides.cues ? overrides.cues['guidance:approaching'] : undefined),
    'guidance:ready': mergeUiCue(DEFAULT_GAME_UI_EFFECTS_CONFIG.cues['guidance:ready'], overrides && overrides.cues ? overrides.cues['guidance:ready'] : undefined),
  }

  return {
    enabled: overrides && overrides.enabled !== undefined ? !!overrides.enabled : DEFAULT_GAME_UI_EFFECTS_CONFIG.enabled,
    cues,
  }
}
