import type { PartyMember } from '../game'
import type { PvpMatchSnapshot, PvpMatchSide } from '../pvpRoguelike'

export type PvpRoguelikeSetupSide<TBuff extends string, TDebuff extends string> = {
  party: PartyMember[]
  resource: number
  cooldowns: Record<string, number>
  enemyHealth: number
  buffs: TBuff[]
  debuffs: TDebuff[]
  castsTowardFree: number
  freeCastReady: boolean
}

export type PvpRoguelikeLiveMatchSetup = {
  id: string
  side: PvpMatchSide
  opponentSide: PvpMatchSide
  opponentName: string
  opponentClassName: string
}

export function createPvpRoguelikeStarterSide<TBuff extends string, TDebuff extends string>(
  partyTemplate: readonly PartyMember[],
  maxResource: number,
): PvpRoguelikeSetupSide<TBuff, TDebuff> {
  return {
    party: partyTemplate.map((member) => ({ ...member })),
    resource: maxResource,
    cooldowns: {},
    enemyHealth: 0,
    buffs: [],
    debuffs: [],
    castsTowardFree: 0,
    freeCastReady: false,
  }
}

export function createPvpRoguelikeMatchStart<
  TBuff extends string,
  TDebuff extends string,
  TEncounter extends { maxHealth: number },
>({
  startStage,
  encounterPool,
  buildSegment,
  partyTemplate,
  opponentPartyTemplate,
  maxResource,
  upgradeChoiceSeconds,
}: {
  startStage: number
  encounterPool: readonly TEncounter[]
  buildSegment: (pool: readonly TEncounter[], stage: number) => TEncounter[]
  partyTemplate: readonly PartyMember[]
  opponentPartyTemplate: readonly PartyMember[]
  maxResource: number
  upgradeChoiceSeconds: number
}) {
  const firstSegment = buildSegment(encounterPool, startStage)
  const firstEncounter = firstSegment[0]
  const playerSide = createPvpRoguelikeStarterSide<TBuff, TDebuff>(partyTemplate, maxResource)
  const opponentSide = createPvpRoguelikeStarterSide<TBuff, TDebuff>(opponentPartyTemplate, maxResource)
  playerSide.enemyHealth = firstEncounter.maxHealth
  opponentSide.enemyHealth = firstEncounter.maxHealth

  return {
    startStage,
    firstSegment,
    firstEncounter,
    playerSide,
    opponentSide,
    defaults: {
      encounterIndex: 0,
      elapsedTicks: 0,
      encountersCleared: 0,
      paused: false,
      targetGroup: 0 as const,
      upgradeTimeLeft: upgradeChoiceSeconds,
      liveUpgradePending: false,
      rewardError: '',
      showEndLog: false,
    },
  }
}

export function createPvpRoguelikeLiveMatchStart<
  TBuff extends string,
  TDebuff extends string,
  TEncounter extends { maxHealth: number },
>({
  match,
  side,
  encounterPool,
  buildSegment,
  partyTemplate,
  opponentPartyTemplate,
  maxResource,
  upgradeChoiceSeconds,
  message,
}: {
  match: PvpMatchSnapshot<PvpRoguelikeSetupSide<TBuff, TDebuff>>
  side: PvpMatchSide
  encounterPool: readonly TEncounter[]
  buildSegment: (pool: readonly TEncounter[], stage: number) => TEncounter[]
  partyTemplate: readonly PartyMember[]
  opponentPartyTemplate: readonly PartyMember[]
  maxResource: number
  upgradeChoiceSeconds: number
  message?: string
}) {
  const opponentSideId: PvpMatchSide = side === 'a' ? 'b' : 'a'
  const opponent = match.players[opponentSideId]
  const opponentTemplate = opponentPartyTemplate.map((member) => ({
    ...member,
    name: member.id === 'mira' ? opponent.characterName : member.name,
  }))
  const setup = createPvpRoguelikeMatchStart<TBuff, TDebuff, TEncounter>({
    startStage: match.startStage,
    encounterPool,
    buildSegment,
    partyTemplate,
    opponentPartyTemplate: opponentTemplate,
    maxResource,
    upgradeChoiceSeconds,
  })
  const liveMatch: PvpRoguelikeLiveMatchSetup = {
    id: match.id,
    side,
    opponentSide: opponentSideId,
    opponentName: opponent.characterName,
    opponentClassName: opponent.className,
  }

  return {
    ...setup,
    liveMatch,
    logText: message ?? `${opponent.characterName} found. Stage ${match.startStage} begins.`,
  }
}
