import { type MapScene } from './mapRenderer'
import { type ControlPointStyleEntry, type CourseLegStyleEntry, type ScoreBandStyleEntry } from '../../game/presentation/courseStyleConfig'

export type RgbaColor = [number, number, number, number]

export interface ResolvedControlStyle {
  entry: ControlPointStyleEntry
  color: RgbaColor
}

export interface ResolvedLegStyle {
  entry: CourseLegStyleEntry
  color: RgbaColor
}

function resolveCompletedBoundaryEntry(scene: MapScene, baseEntry: ControlPointStyleEntry): ControlPointStyleEntry {
  const completedPalette = scene.gameMode === 'score-o'
    ? scene.courseStyleConfig.scoreO.controls.collected
    : scene.courseStyleConfig.sequential.controls.completed

  return {
    ...baseEntry,
    colorHex: completedPalette.colorHex,
    labelColorHex: completedPalette.labelColorHex || baseEntry.labelColorHex,
    glowStrength: 0,
  }
}

function mergeControlStyleEntries(
  baseEntry: ControlPointStyleEntry,
  overrideEntry?: ControlPointStyleEntry | null,
): ControlPointStyleEntry {
  if (!overrideEntry) {
    return baseEntry
  }

  return {
    ...baseEntry,
    ...overrideEntry,
  }
}

function mergeLegStyleEntries(
  baseEntry: CourseLegStyleEntry,
  overrideEntry?: CourseLegStyleEntry | null,
): CourseLegStyleEntry {
  if (!overrideEntry) {
    return baseEntry
  }

  return {
    ...baseEntry,
    ...overrideEntry,
  }
}

export function hexToRgbaColor(hex: string, alphaOverride?: number): RgbaColor {
  const fallback: RgbaColor = [1, 1, 1, alphaOverride !== undefined ? alphaOverride : 1]
  if (typeof hex !== 'string' || !hex || hex.charAt(0) !== '#') {
    return fallback
  }

  const normalized = hex.slice(1)
  if (normalized.length !== 6 && normalized.length !== 8) {
    return fallback
  }

  const red = parseInt(normalized.slice(0, 2), 16)
  const green = parseInt(normalized.slice(2, 4), 16)
  const blue = parseInt(normalized.slice(4, 6), 16)
  const alpha = normalized.length === 8 ? parseInt(normalized.slice(6, 8), 16) : 255
  if (!Number.isFinite(red) || !Number.isFinite(green) || !Number.isFinite(blue) || !Number.isFinite(alpha)) {
    return fallback
  }

  return [
    red / 255,
    green / 255,
    blue / 255,
    alphaOverride !== undefined ? alphaOverride : alpha / 255,
  ]
}

function resolveScoreBandStyle(scene: MapScene, sequence: number): ScoreBandStyleEntry | null {
  const score = scene.controlScoresBySequence[sequence]
  if (score === undefined) {
    return null
  }

  const bands = scene.courseStyleConfig.scoreO.controls.scoreBands
  for (let index = 0; index < bands.length; index += 1) {
    const band = bands[index]
    if (score >= band.min && score <= band.max) {
      return band
    }
  }

  return null
}

export function resolveControlStyle(scene: MapScene, kind: 'start' | 'control' | 'finish', sequence: number | null, index?: number): ResolvedControlStyle {
  if (kind === 'start') {
    const baseEntry = index !== undefined && scene.startStyleOverrides[index]
      ? scene.startStyleOverrides[index]
      : scene.gameMode === 'score-o'
      ? scene.courseStyleConfig.scoreO.controls.start
      : scene.courseStyleConfig.sequential.controls.start
    const entry = scene.completedStart
      ? resolveCompletedBoundaryEntry(scene, baseEntry)
      : baseEntry
    return { entry, color: hexToRgbaColor(entry.colorHex) }
  }

  if (kind === 'finish') {
    const baseEntry = index !== undefined && scene.finishStyleOverrides[index]
      ? scene.finishStyleOverrides[index]
      : scene.gameMode === 'score-o'
      ? scene.courseStyleConfig.scoreO.controls.finish
      : scene.courseStyleConfig.sequential.controls.finish
    const entry = scene.completedFinish
      ? resolveCompletedBoundaryEntry(scene, baseEntry)
      : baseEntry
    return { entry, color: hexToRgbaColor(entry.colorHex) }
  }

  if (sequence === null) {
    const entry = scene.courseStyleConfig.sequential.controls.default
    return { entry, color: hexToRgbaColor(entry.colorHex) }
  }
  const sequenceOverride = scene.controlStyleOverridesBySequence[sequence]
  const defaultOverride = scene.defaultControlStyleOverride

  if (scene.gameMode === 'score-o') {
    if (scene.completedControlSequences.includes(sequence)) {
      const entry = mergeControlStyleEntries(
        scene.courseStyleConfig.scoreO.controls.collected,
        sequenceOverride || defaultOverride,
      )
      return { entry, color: hexToRgbaColor(entry.colorHex) }
    }

    if (scene.focusedControlSequences.includes(sequence)) {
      const bandEntry = resolveScoreBandStyle(scene, sequence)
      const baseEntry = bandEntry || scene.courseStyleConfig.scoreO.controls.default
      const focusedEntry = scene.courseStyleConfig.scoreO.controls.focused
      const focusedMergedEntry: ControlPointStyleEntry = {
        ...baseEntry,
        ...focusedEntry,
        colorHex: baseEntry.colorHex,
      }
      const entry = mergeControlStyleEntries(focusedMergedEntry, sequenceOverride || defaultOverride)
      return { entry, color: hexToRgbaColor(entry.colorHex) }
    }

    const bandEntry = resolveScoreBandStyle(scene, sequence)
    const entry = mergeControlStyleEntries(
      bandEntry || scene.courseStyleConfig.scoreO.controls.default,
      sequenceOverride || defaultOverride,
    )
    return { entry, color: hexToRgbaColor(entry.colorHex) }
  }

  if (scene.readyControlSequences.includes(sequence) || scene.activeControlSequences.includes(sequence)) {
    const entry = mergeControlStyleEntries(
      scene.courseStyleConfig.sequential.controls.current,
      sequenceOverride || defaultOverride,
    )
    return { entry, color: hexToRgbaColor(entry.colorHex) }
  }

  if (scene.completedControlSequences.includes(sequence)) {
    const entry = mergeControlStyleEntries(
      scene.courseStyleConfig.sequential.controls.completed,
      sequenceOverride || defaultOverride,
    )
    return { entry, color: hexToRgbaColor(entry.colorHex) }
  }

  if (scene.skippedControlSequences.includes(sequence)) {
    const entry = mergeControlStyleEntries(
      scene.courseStyleConfig.sequential.controls.skipped,
      sequenceOverride || defaultOverride,
    )
    return { entry, color: hexToRgbaColor(entry.colorHex) }
  }

  const entry = mergeControlStyleEntries(
    scene.courseStyleConfig.sequential.controls.default,
    sequenceOverride || defaultOverride,
  )
  return { entry, color: hexToRgbaColor(entry.colorHex) }
}

export function resolveLegStyle(scene: MapScene, index: number): ResolvedLegStyle {
  if (scene.gameMode === 'score-o') {
    const entry = mergeLegStyleEntries(
      scene.courseStyleConfig.sequential.legs.default,
      scene.legStyleOverridesByIndex[index] || scene.defaultLegStyleOverride,
    )
    return { entry, color: hexToRgbaColor(entry.colorHex) }
  }

  const completed = scene.completedLegIndices.includes(index)
  const baseEntry = completed ? scene.courseStyleConfig.sequential.legs.completed : scene.courseStyleConfig.sequential.legs.default
  const entry = mergeLegStyleEntries(baseEntry, scene.legStyleOverridesByIndex[index] || scene.defaultLegStyleOverride)
  return { entry, color: hexToRgbaColor(entry.colorHex) }
}
