import { useMemo } from 'react'
import type { MilitarySituation } from '@/data/mockData'
import { useSituationStore } from '@/store/situationStore'
import { usePlaybackStore, REPLAY_START, REPLAY_END } from '@/store/playbackStore'

/** 盟军打击伊朗结束时刻：伊朗战损在此阶段增长 */
const ALLIED_STRIKE_END = '2026-02-28T04:00:00.000Z'
/** 伊朗反击开始时刻：美军战损在此阶段增长 */
const IRAN_RETALIATION_START = '2026-02-28T06:00:00.000Z'

/** 将系列时间映射到回放日以便按当天时刻插值 */
function toReplayDay(iso: string, baseDay: string): string {
  const d = new Date(iso)
  const [y, m, day] = baseDay.slice(0, 10).split('-').map(Number)
  return new Date(y, (m || 1) - 1, day || 1, d.getUTCHours(), d.getUTCMinutes(), 0, 0).toISOString()
}

/** 判断数据库时间戳是否已到回放时刻（用于按日期刻度自动追加） */
function atOrBefore(ts: string | null | undefined, playbackTime: string): boolean {
  if (!ts) return true
  return new Date(ts).getTime() <= new Date(playbackTime).getTime()
}

function interpolateAt(
  series: { time: string; value: number }[],
  at: string,
  baseDay = '2026-03-01'
): number {
  if (series.length === 0) return 0
  const t = new Date(at).getTime()
  const mapped = series.map((p) => ({
    time: toReplayDay(p.time, baseDay),
    value: p.value,
  }))
  const sorted = [...mapped].sort((a, b) => new Date(a.time).getTime() - new Date(b.time).getTime())
  const before = sorted.filter((p) => new Date(p.time).getTime() <= t)
  const after = sorted.filter((p) => new Date(p.time).getTime() > t)
  if (before.length === 0) return sorted[0].value
  if (after.length === 0) return sorted[sorted.length - 1].value
  const a = before[before.length - 1]
  const b = after[0]
  const ta = new Date(a.time).getTime()
  const tb = new Date(b.time).getTime()
  const f = tb === ta ? 1 : (t - ta) / (tb - ta)
  return a.value + f * (b.value - a.value)
}

function linearProgress(start: string, end: string, at: string): number {
  const ts = new Date(start).getTime()
  const te = new Date(end).getTime()
  const ta = new Date(at).getTime()
  if (ta <= ts) return 0
  if (ta >= te) return 1
  return (ta - ts) / (te - ts)
}

/** 根据回放时刻派生态势数据：按日期刻度过滤，只显示 attacked_at / struck_at / timestamp 不晚于 playbackTime 的数据库数据 */
export function useReplaySituation(): MilitarySituation {
  const situation = useSituationStore((s) => s.situation)
  const { isReplayMode, playbackTime } = usePlaybackStore()

  return useMemo(() => {
    if (!isReplayMode) return situation

    // 战损阶段：伊朗（盟军打击 02:00–04:00）先行，美军（伊朗反击 06:00 起）随后
    const progressIran = linearProgress(REPLAY_START, ALLIED_STRIKE_END, playbackTime)
    const progressUs = linearProgress(IRAN_RETALIATION_START, REPLAY_END, playbackTime)
    const lerpIran = (a: number, b: number) => Math.round(a + progressIran * (b - a))
    const lerpUs = (a: number, b: number) => Math.round(a + progressUs * (b - a))

    // 华尔街趋势、反击情绪：按回放日当天的时刻插值，保留两位小数避免穿模
    const replayDay = playbackTime.slice(0, 10)
    const wsValue = Math.round(interpolateAt(situation.usForces.wallStreetInvestmentTrend, playbackTime, replayDay) * 100) / 100
    const retValue = Math.round(interpolateAt(situation.iranForces.retaliationSentimentHistory, playbackTime, replayDay) * 100) / 100

    const usLoss = situation.usForces.combatLosses
    const irLoss = situation.iranForces.combatLosses
    const civTotal = situation.civilianCasualtiesTotal ?? { killed: 0, wounded: 0 }
    const usLossesAt = {
      bases: {
        destroyed: lerpUs(0, usLoss.bases.destroyed),
        damaged: lerpUs(0, usLoss.bases.damaged),
      },
      personnelCasualties: {
        killed: lerpUs(0, usLoss.personnelCasualties.killed),
        wounded: lerpUs(0, usLoss.personnelCasualties.wounded),
      },
      civilianCasualties: { killed: 0, wounded: 0 },
      aircraft: lerpUs(0, usLoss.aircraft),
      warships: lerpUs(0, usLoss.warships),
      armor: lerpUs(0, usLoss.armor),
      vehicles: lerpUs(0, usLoss.vehicles),
      drones: lerpUs(0, usLoss.drones ?? 0),
      missiles: lerpUs(0, usLoss.missiles ?? 0),
      helicopters: lerpUs(0, usLoss.helicopters ?? 0),
      submarines: lerpUs(0, usLoss.submarines ?? 0),
      carriers: lerpUs(0, usLoss.carriers ?? 0),
      civilianShips: lerpUs(0, usLoss.civilianShips ?? 0),
      airportPort: lerpUs(0, usLoss.airportPort ?? 0),
    }
    const irLossesAt = {
      bases: {
        destroyed: lerpIran(0, irLoss.bases.destroyed),
        damaged: lerpIran(0, irLoss.bases.damaged),
      },
      personnelCasualties: {
        killed: lerpIran(0, irLoss.personnelCasualties.killed),
        wounded: lerpIran(0, irLoss.personnelCasualties.wounded),
      },
      civilianCasualties: { killed: 0, wounded: 0 },
      aircraft: lerpIran(0, irLoss.aircraft),
      warships: lerpIran(0, irLoss.warships),
      armor: lerpIran(0, irLoss.armor),
      vehicles: lerpIran(0, irLoss.vehicles),
      drones: lerpIran(0, irLoss.drones ?? 0),
      missiles: lerpIran(0, irLoss.missiles ?? 0),
      helicopters: lerpIran(0, irLoss.helicopters ?? 0),
      submarines: lerpIran(0, irLoss.submarines ?? 0),
      carriers: lerpIran(0, irLoss.carriers ?? 0),
      civilianShips: lerpIran(0, irLoss.civilianShips ?? 0),
      airportPort: lerpIran(0, irLoss.airportPort ?? 0),
    }

    // 被袭基地：按 DB attacked_at 过滤，只显示已到回放时刻的遭袭点
    const usLocs = situation.usForces.keyLocations || []
    const usLocsAt = usLocs.map((loc) => {
      if (loc.status === 'attacked' && !atOrBefore(loc.attacked_at, playbackTime)) {
        return { ...loc, status: 'operational' as const }
      }
      return { ...loc }
    })

    const irLocs = situation.iranForces.keyLocations || []
    const irLocsAt = irLocs.map((loc) => {
      if ((loc.status === 'attacked' || loc.status === 'damaged') && !atOrBefore(loc.attacked_at, playbackTime)) {
        return { ...loc, status: 'operational' as const }
      }
      return { ...loc }
    })

    // mapData：按 struck_at / attacked_at 过滤；打击线固定顺序 以色列 → 林肯 → 福特，保证回放时以色列动画先出现
    const mapData = situation.mapData
    const mapDataAt = mapData
      ? (() => {
          const filtered = mapData.strikeLines.map((line) => ({
            sourceId: line.sourceId,
            targets: line.targets.filter((t) => atOrBefore(t.struck_at, playbackTime)),
          }))
          const order = ['israel', 'lincoln', 'ford']
          const ordered = order.map((id) => filtered.find((l) => l.sourceId === id)).filter(Boolean) as typeof filtered
          const rest = filtered.filter((l) => !order.includes(l.sourceId))
          const strikeLines = [...ordered, ...rest]
          return {
            attackedTargets: (usLocsAt.filter((l) => l.status === 'attacked') as { lng: number; lat: number }[]).map(
              (l) => [l.lng, l.lat] as [number, number]
            ),
            strikeSources: mapData.strikeSources,
            strikeLines,
          }
        })()
      : undefined

    return {
      ...situation,
      lastUpdated: playbackTime,
      civilianCasualtiesTotal: {
        killed: lerpIran(0, civTotal.killed),
        wounded: lerpIran(0, civTotal.wounded),
      },
      usForces: {
        ...situation.usForces,
        keyLocations: usLocsAt,
        combatLosses: usLossesAt,
        wallStreetInvestmentTrend: [
          ...situation.usForces.wallStreetInvestmentTrend.filter((p) => new Date(p.time).getTime() <= new Date(playbackTime).getTime()),
          { time: playbackTime, value: wsValue },
        ].slice(-20),
      },
      iranForces: {
        ...situation.iranForces,
        keyLocations: irLocsAt,
        combatLosses: irLossesAt,
        retaliationSentiment: retValue,
        retaliationSentimentHistory: [
          ...situation.iranForces.retaliationSentimentHistory.filter((p) => new Date(p.time).getTime() <= new Date(playbackTime).getTime()),
          { time: playbackTime, value: retValue },
        ].slice(-20),
      },
      recentUpdates: (situation.recentUpdates || []).filter(
        (u) => new Date(u.timestamp).getTime() <= new Date(playbackTime).getTime()
      ),
      conflictEvents: (situation.conflictEvents || []).filter(
        (e) => new Date(e.event_time).getTime() <= new Date(playbackTime).getTime()
      ),
      conflictStats: situation.conflictStats || { total_events: 0, high_impact_events: 0, estimated_casualties: 0, estimated_strike_count: 0 },
      mapData: mapDataAt,
    }
  }, [situation, isReplayMode, playbackTime])
}
