import { requestGameApiJson } from './gameRepository'

export type PvpContentType = 'dungeon' | 'raid' | 'stadium'
export type CpuDifficulty = 1 | 2 | 3 | 4 | 5
export type PvpMatchSide = 'a' | 'b'
export type PvpMatchStatus = 'playing' | 'upgrade-choice' | 'shop' | 'won' | 'lost'

export type PvpPlayerInfo = {
  side: PvpMatchSide
  accountId: number
  characterId: number
  characterName: string
  className: string
}

export type PvpUpgradeChoicePayload = {
  encounterIndex: number
  buffId: string
  debuffId: string
  purchases?: string[]
  shopReady?: boolean
}

export type PvpMatchSnapshot<TSideState = unknown> = {
  id: string
  contentType: PvpContentType
  startStage: number
  createdAt: number
  players: Record<PvpMatchSide, PvpPlayerInfo>
  states: Partial<Record<PvpMatchSide, TSideState>>
  statuses: Partial<Record<PvpMatchSide, PvpMatchStatus>>
  progress: Partial<Record<PvpMatchSide, {
    stage: number
    encounterIndex: number
    encountersCleared: number
    enemyHealth: number
    alive: boolean
    elapsedTicks: number
  }>>
  upgradeChoices: Partial<Record<PvpMatchSide, Record<string, PvpUpgradeChoicePayload>>>
  rematchRequests?: Partial<Record<PvpMatchSide, boolean>>
  updatedAt: number
}

export type PvpQueueResponse<TSideState = unknown> = {
  ticketId: string
  status: 'waiting' | 'matched'
  match?: PvpMatchSnapshot<TSideState>
  side?: PvpMatchSide
}

export type PvpRematchResponse<TSideState = unknown> = {
  status: 'waiting' | 'matched'
  match?: PvpMatchSnapshot<TSideState>
  side?: PvpMatchSide
}

export type CpuPvpLeaderboardEntry = {
  characterName: string
  className: string
  contentType: PvpContentType
  encountersCleared: number
  cpuDifficulty: CpuDifficulty
  result: 'victory' | 'defeat'
  completedAt: string
}

const cpuLeaderboardKey = 'chronicle.pvpCpuLeaderboard.v1'
const checkpointKey = 'chronicle.pvpRoguelikeCheckpoint.v1'

export function randomCpuDifficulty(): CpuDifficulty {
  return (Math.floor(Math.random() * 5) + 1) as CpuDifficulty
}

export function loadCpuPvpLeaderboard(contentType?: PvpContentType): CpuPvpLeaderboardEntry[] {
  try {
    const raw = JSON.parse(localStorage.getItem(cpuLeaderboardKey) ?? '[]') as CpuPvpLeaderboardEntry[]
    return raw
      .filter((entry) => !contentType || entry.contentType === contentType)
      .sort((left, right) =>
        right.encountersCleared - left.encountersCleared
        || right.cpuDifficulty - left.cpuDifficulty
        || right.completedAt.localeCompare(left.completedAt),
      )
      .slice(0, 12)
  } catch {
    return []
  }
}

export function recordCpuPvpLeaderboard(entry: CpuPvpLeaderboardEntry) {
  const current = loadCpuPvpLeaderboard()
  const next = [...current, entry]
    .sort((left, right) =>
      right.encountersCleared - left.encountersCleared
      || right.cpuDifficulty - left.cpuDifficulty
      || right.completedAt.localeCompare(left.completedAt),
    )
    .slice(0, 30)
  localStorage.setItem(cpuLeaderboardKey, JSON.stringify(next))
}

function checkpointStorageKey(characterId: number, contentType: PvpContentType) {
  return `${checkpointKey}:${characterId}:${contentType}`
}

export function loadPvpRoguelikeCheckpoint(characterId: number, contentType: PvpContentType) {
  const value = Number(localStorage.getItem(checkpointStorageKey(characterId, contentType)) ?? 1)
  return Number.isInteger(value) && value >= 5 ? value : 1
}

export function recordPvpRoguelikeCheckpoint(
  characterId: number,
  contentType: PvpContentType,
  stage: number,
) {
  if (stage < 5 || stage % 5 !== 0) return loadPvpRoguelikeCheckpoint(characterId, contentType)
  const current = loadPvpRoguelikeCheckpoint(characterId, contentType)
  const next = Math.max(current, stage)
  localStorage.setItem(checkpointStorageKey(characterId, contentType), String(next))
  return next
}

export function joinPvpQueue<TSideState>(
  contentType: PvpContentType,
  startStage: number,
): Promise<PvpQueueResponse<TSideState>> {
  return requestGameApiJson('/api/pvp/queue', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ contentType, startStage }),
  })
}

export function checkPvpQueue<TSideState>(ticketId: string): Promise<PvpQueueResponse<TSideState>> {
  return requestGameApiJson(`/api/pvp/queue/${encodeURIComponent(ticketId)}`)
}

export function cancelPvpQueue(ticketId: string): Promise<{ ok: true }> {
  return requestGameApiJson(`/api/pvp/queue/${encodeURIComponent(ticketId)}`, {
    method: 'DELETE',
  })
}

export function publishPvpMatchState<TSideState>(
  matchId: string,
  payload: {
    state: TSideState
    status: PvpMatchStatus
    stage: number
    encounterIndex: number
    encountersCleared: number
    enemyHealth: number
    alive: boolean
    elapsedTicks: number
  },
): Promise<PvpMatchSnapshot<TSideState>> {
  return requestGameApiJson(`/api/pvp/matches/${encodeURIComponent(matchId)}/state`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  })
}

export function loadPvpMatch<TSideState>(matchId: string): Promise<PvpMatchSnapshot<TSideState>> {
  return requestGameApiJson(`/api/pvp/matches/${encodeURIComponent(matchId)}`)
}

export function submitPvpUpgradeChoice(
  matchId: string,
  payload: PvpUpgradeChoicePayload,
): Promise<PvpMatchSnapshot> {
  return requestGameApiJson(`/api/pvp/matches/${encodeURIComponent(matchId)}/upgrade-choice`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(payload),
  })
}

export function requestPvpRematch<TSideState>(matchId: string): Promise<PvpRematchResponse<TSideState>> {
  return requestGameApiJson(`/api/pvp/matches/${encodeURIComponent(matchId)}/rematch`, {
    method: 'POST',
  })
}
