import type {
  HistoryListItem,
  HistoryRecord,
  HistoryUploadPayload,
  HistoryUploadResponse,
  MatchResultsRecord,
} from '../types'

export async function loadMatchResults(time: string) {
  const response = await fetch(`/api/match-results/${time}`)
  const payload = (await response.json()) as {
    ok?: boolean
    message?: string
    data?: MatchResultsRecord
  }

  if (response.status === 404) {
    return null
  }

  if (!response.ok || !payload.ok) {
    throw new Error(payload.message ?? '無法讀取對戰資料。')
  }

  return payload.data ?? null
}

export async function saveMatchHistory(payload: HistoryUploadPayload) {
  const response = await fetch('/api/history', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(payload),
  })

  const result = (await response.json()) as {
    ok?: boolean
    message?: string
    data?: HistoryUploadResponse
  }

  if (!response.ok || !result.ok || !result.data) {
    throw new Error(result.message ?? '無法上傳戰績。')
  }

  return result.data
}

export async function loadHistoryList() {
  const response = await fetch('/api/history')
  const payload = (await response.json()) as {
    ok?: boolean
    message?: string
    data?: HistoryRecord[]
  }

  if (!response.ok || !payload.ok) {
    throw new Error(payload.message ?? '無法讀取歷史戰績。')
  }

  return (payload.data ?? []).map(normalizeHistoryRecord)
}

export async function deleteHistoryItem(id: number) {
  const response = await fetch(`/api/history/${id}`, {
    method: 'DELETE',
  })

  const payload = (await response.json()) as {
    ok?: boolean
    message?: string
  }

  if (!response.ok || !payload.ok) {
    throw new Error(payload.message ?? '刪除歷史戰績失敗。')
  }
}

function normalizeHistoryRecord(record: HistoryRecord): HistoryListItem {
  const score = parseJson<[number, number]>(record.score, [0, 0])
  const players = parseJson<string[]>(record.players, [])
  const team = parseJson<[string[], string[]]>(record.team, [[], []])
  const scoreList = parseJson<Array<[number, number, number, 0 | 1]>>(
    record.scoreList,
    [],
  )
  const leftTeamName = team[0]?.join(' / ') || players.slice(0, 2).join(' / ') || '-'
  const rightTeamName = team[1]?.join(' / ') || players.slice(2, 4).join(' / ') || '-'
  const winnerTeamName = score[0] >= score[1] ? leftTeamName : rightTeamName

  return {
    id: record.id,
    time: record.time,
    playedAt: new Date(record.time * 1000).toLocaleString('zh-TW', { hour12: false }),
    dayOfWeek: record.dayOfWeek,
    dayLabel: getDayLabel(record.dayOfWeek),
    score,
    winScore: record.winScore,
    type: record.type,
    typeLabel: record.type === 1 ? '單打' : '雙打',
    players,
    team,
    scoreList,
    leftTeamName,
    rightTeamName,
    winnerTeamName,
  }
}

function parseJson<T>(value: string | null, fallback: T): T {
  if (!value) {
    return fallback
  }

  try {
    return JSON.parse(value) as T
  } catch {
    return fallback
  }
}

function getDayLabel(dayOfWeek: number) {
  const labels = ['週日', '週一', '週二', '週三', '週四', '週五', '週六']
  return labels[dayOfWeek] ?? '-'
}
