import {
  type GameContentExperienceConfig,
  type GameContentExperienceConfigOverride,
  type GameDefinition,
  type GameControl,
  type GameControlDisplayContent,
  type GameControlDisplayContentOverride,
  type PunchPolicyType,
} from '../core/gameDefinition'
import {
  resolveContentCardCtaConfig,
} from '../experience/contentCard'
import { type OrienteeringCourseData } from '../../utils/orienteeringCourse'
import {
  getDefaultSkipRadiusMeters,
  getGameModeDefaults,
  resolveDefaultControlScore,
} from '../core/gameModeDefaults'

function sortBySequence<T extends { sequence: number | null }>(items: T[]): T[] {
  return [...items].sort((a, b) => (a.sequence || 0) - (b.sequence || 0))
}

function buildDisplayBody(label: string, sequence: number | null): string {
  if (typeof sequence === 'number') {
    return `检查点 ${sequence} · ${label || String(sequence)}`
  }

  return label
}

function applyExperienceOverride(
  baseExperience: GameContentExperienceConfig | null,
  override: GameContentExperienceConfigOverride | undefined,
): GameContentExperienceConfig | null {
  if (!override) {
    return baseExperience
  }

  if (override.type === 'native') {
    return {
      type: 'native',
      url: null,
      bridge: 'content-v1',
      fallback: 'native',
      presentation: 'sheet',
    }
  }

  if (override.type === 'h5' && override.url) {
    return {
      type: 'h5',
      url: override.url,
      bridge: override.bridge || (baseExperience ? baseExperience.bridge : 'content-v1'),
      fallback: override.fallback || 'native',
      presentation: override.presentation || (baseExperience ? baseExperience.presentation : 'sheet'),
    }
  }

  return baseExperience
}

function applyDisplayContentOverride(
  baseContent: GameControlDisplayContent,
  override: GameControlDisplayContentOverride | undefined,
): GameControlDisplayContent {
  if (!override) {
    return baseContent
  }

  return {
    template: override.template || baseContent.template,
    title: override.title || baseContent.title,
    body: override.body || baseContent.body,
    autoPopup: override.autoPopup !== undefined ? override.autoPopup : baseContent.autoPopup,
    once: override.once !== undefined ? override.once : baseContent.once,
    priority: override.priority !== undefined ? override.priority : baseContent.priority,
    clickTitle: override.clickTitle !== undefined ? override.clickTitle : baseContent.clickTitle,
    clickBody: override.clickBody !== undefined ? override.clickBody : baseContent.clickBody,
    ctas: override.ctas && override.ctas.length
      ? override.ctas
        .map((item) => resolveContentCardCtaConfig(item))
        .filter((item): item is NonNullable<typeof item> => !!item)
      : baseContent.ctas,
    contentExperience: applyExperienceOverride(baseContent.contentExperience, override.contentExperience),
    clickExperience: applyExperienceOverride(baseContent.clickExperience, override.clickExperience),
  }
}

export function buildGameDefinitionFromCourse(
  course: OrienteeringCourseData,
  controlRadiusMeters: number,
  mode: GameDefinition['mode'] = 'classic-sequential',
  sessionCloseAfterMs?: number,
  sessionCloseWarningMs?: number,
  minCompletedControlsBeforeFinish?: number,
  autoFinishOnLastControl?: boolean,
  punchPolicy: PunchPolicyType = 'enter-confirm',
  punchRadiusMeters = 5,
  requiresFocusSelection?: boolean,
  skipEnabled?: boolean,
  skipRadiusMeters?: number,
  skipRequiresConfirm?: boolean,
  controlScoreOverrides: Record<string, number> = {},
  defaultControlContentOverride: GameControlDisplayContentOverride | null = null,
  controlContentOverrides: Record<string, GameControlDisplayContentOverride> = {},
  defaultControlScore: number | null = null,
): GameDefinition {
  const controls: GameControl[] = []
  const modeDefaults = getGameModeDefaults(mode)
  const resolvedSessionCloseAfterMs = sessionCloseAfterMs !== undefined
    ? sessionCloseAfterMs
    : modeDefaults.sessionCloseAfterMs
  const resolvedSessionCloseWarningMs = sessionCloseWarningMs !== undefined
    ? sessionCloseWarningMs
    : modeDefaults.sessionCloseWarningMs
  const resolvedMinCompletedControlsBeforeFinish = minCompletedControlsBeforeFinish !== undefined
    ? minCompletedControlsBeforeFinish
    : modeDefaults.minCompletedControlsBeforeFinish
  const resolvedRequiresFocusSelection = requiresFocusSelection !== undefined
    ? requiresFocusSelection
    : modeDefaults.requiresFocusSelection
  const resolvedSkipEnabled = skipEnabled !== undefined
    ? skipEnabled
    : modeDefaults.skipEnabled
  const resolvedSkipRadiusMeters = skipRadiusMeters !== undefined
    ? skipRadiusMeters
    : getDefaultSkipRadiusMeters(mode, punchRadiusMeters)
  const resolvedSkipRequiresConfirm = skipRequiresConfirm !== undefined
    ? skipRequiresConfirm
    : modeDefaults.skipRequiresConfirm
  const resolvedAutoFinishOnLastControl = autoFinishOnLastControl !== undefined
    ? autoFinishOnLastControl
    : modeDefaults.autoFinishOnLastControl
  const resolvedDefaultControlScore = resolveDefaultControlScore(mode, defaultControlScore)

  for (let startIndex = 0; startIndex < course.layers.starts.length; startIndex += 1) {
    const start = course.layers.starts[startIndex]
    const startId = `start-${startIndex + 1}`
    controls.push({
      id: startId,
      code: start.label || 'S',
      label: start.label || 'Start',
      kind: 'start',
      point: start.point,
      sequence: null,
      score: null,
      displayContent: applyDisplayContentOverride({
        template: 'focus',
        title: '比赛开始',
        body: `${start.label || '开始点'}已激活，按提示前往下一个目标点。`,
        autoPopup: false,
        once: false,
        priority: 1,
        clickTitle: null,
        clickBody: null,
        ctas: [],
        contentExperience: null,
        clickExperience: null,
      }, controlContentOverrides[startId]),
    })
  }

  for (const control of sortBySequence(course.layers.controls)) {
    const label = control.label || String(control.sequence)
    const controlId = `control-${control.sequence}`
    const score = controlId in controlScoreOverrides
      ? controlScoreOverrides[controlId]
      : resolvedDefaultControlScore
    controls.push({
      id: controlId,
      code: label,
      label,
      kind: 'control',
      point: control.point,
      sequence: control.sequence,
      score,
      displayContent: applyDisplayContentOverride(
        applyDisplayContentOverride({
          template: 'story',
          title: score !== null ? `收集 ${label} (+${score}分)` : `收集 ${label}`,
          body: score !== null ? `${buildDisplayBody(label, control.sequence)} · ${score}分` : buildDisplayBody(label, control.sequence),
          autoPopup: false,
          once: false,
          priority: 1,
          clickTitle: null,
          clickBody: null,
          ctas: [],
          contentExperience: null,
          clickExperience: null,
        }, defaultControlContentOverride || undefined),
        controlContentOverrides[controlId],
      ),
    })
  }

  for (let finishIndex = 0; finishIndex < course.layers.finishes.length; finishIndex += 1) {
    const finish = course.layers.finishes[finishIndex]
    const finishId = `finish-${finishIndex + 1}`
    const legacyFinishId = `finish-${controls.length + 1}`
    controls.push({
      id: finishId,
      code: finish.label || 'F',
      label: finish.label || 'Finish',
      kind: 'finish',
      point: finish.point,
      sequence: null,
      score: null,
      displayContent: applyDisplayContentOverride({
        template: 'focus',
        title: '完成路线',
        body: `${finish.label || '结束点'}已完成，准备查看本局结果。`,
        autoPopup: false,
        once: false,
        priority: 2,
        clickTitle: null,
        clickBody: null,
        ctas: [],
        contentExperience: null,
        clickExperience: null,
      }, controlContentOverrides[finishId] || controlContentOverrides[legacyFinishId]),
    })
  }

  return {
    id: `course-${course.title || 'default'}`,
    mode,
    title: course.title || (mode === 'score-o' ? 'Score-O' : 'Classic Sequential'),
    controlRadiusMeters,
    sessionCloseAfterMs: resolvedSessionCloseAfterMs,
    sessionCloseWarningMs: resolvedSessionCloseWarningMs,
    minCompletedControlsBeforeFinish: resolvedMinCompletedControlsBeforeFinish,
    punchRadiusMeters,
    punchPolicy,
    requiresFocusSelection: resolvedRequiresFocusSelection,
    skipEnabled: resolvedSkipEnabled,
    skipRadiusMeters: resolvedSkipRadiusMeters,
    skipRequiresConfirm: resolvedSkipRequiresConfirm,
    controls,
    autoFinishOnLastControl: resolvedAutoFinishOnLastControl,
  }
}
