import { describe, expect, it } from "vitest"
import {
  API_TO_FORMAT,
  FORMAT_MAP,
  FORMAT_TO_API,
  FORMATS,
  isScrambleVsSolo,
  isTwoSided,
  ORDINARY_FORMATS,
  showsTeamStep,
  SCRAMBLE_VS_SOLO,
  SIDE_IS_UNIT_FORMAT,
  TWO_SIDED,
  apiStatLevel,
} from "./formats"

// FORMAT_TO_API er en Record<FormatId, string> -- TypeScript håndhever
// allerede ved kompilering at ALLE FormatId-verdier har en oppføring der.
// Det disse testene fanger opp er det tsc IKKE fanger: FORMATS (en vanlig
// array) og FORMAT_MAP (bygget med en `as`-cast som omgår typesjekk) kan
// bli ufullstendige uten at kompilatoren sier ifra -- akkurat den typen
// stille avvik minnenotatet om "format-klassifiseringssett" advarer mot.

describe("fullstendighet på tvers av format-lister", () => {
  const apiFormatIds = Object.keys(FORMAT_TO_API) as (keyof typeof FORMAT_TO_API)[]

  it("FORMATS har nøyaktig én oppføring per FormatId i FORMAT_TO_API", () => {
    const formatsIds = FORMATS.map((f) => f.id).sort()
    expect(formatsIds).toEqual([...apiFormatIds].sort())
  })

  it("FORMAT_MAP har en oppføring for hver FormatId (fanger opp `as`-castens blindsone)", () => {
    for (const id of apiFormatIds) {
      expect(FORMAT_MAP[id], `FORMAT_MAP mangler "${id}"`).toBeDefined()
      expect(FORMAT_MAP[id].id).toBe(id)
    }
  })

  it("ingen to FormatId deler samme API-verdi (ellers ville API_TO_FORMAT stille mistet en)", () => {
    const apiValues = Object.values(FORMAT_TO_API)
    expect(new Set(apiValues).size).toBe(apiValues.length)
  })

  it("API_TO_FORMAT er en eksakt invers av FORMAT_TO_API", () => {
    for (const id of apiFormatIds) {
      const apiValue = FORMAT_TO_API[id]
      expect(API_TO_FORMAT[apiValue]).toBe(id)
    }
    expect(Object.keys(API_TO_FORMAT)).toHaveLength(apiFormatIds.length)
  })

  it.each([
    ["TWO_SIDED", TWO_SIDED],
    ["SCRAMBLE_VS_SOLO", SCRAMBLE_VS_SOLO],
    ["SIDE_IS_UNIT_FORMAT", SIDE_IS_UNIT_FORMAT],
    ["ORDINARY_FORMATS", ORDINARY_FORMATS],
  ])("%s inneholder kun gyldige FormatId (fanger opp skrivefeil som 'scramble_2')", (_name, list) => {
    for (const id of list) {
      expect(apiFormatIds, `"${id}" er ikke en gyldig FormatId`).toContain(id)
    }
  })
})

describe("isTwoSided / isScrambleVsSolo / showsTeamStep", () => {
  it("foursome er to-sidet, singel er det ikke", () => {
    expect(isTwoSided("foursome")).toBe(true)
    expect(isTwoSided("slagspill")).toBe(false)
  })

  it("scramblevssolo(match) er scramble-mot-solo, ingen andre format er det", () => {
    expect(isScrambleVsSolo("scramblevssolo")).toBe(true)
    expect(isScrambleVsSolo("scramblevssolomatch")).toBe(true)
    expect(isScrambleVsSolo("foursome")).toBe(false)
  })

  it("lag-steget vises for to-sidede, money ball og scramble-mot-solo -- ikke for ordinære", () => {
    expect(showsTeamStep("foursome")).toBe(true)
    expect(showsTeamStep("moneyball")).toBe(true)
    expect(showsTeamStep("scramblevssolo")).toBe(true)
    expect(showsTeamStep("slagspill")).toBe(false)
    expect(showsTeamStep("stableford")).toBe(false)
  })
})

describe("apiStatLevel", () => {
  it("mapper alle tre kjente statistikk-nivåer korrekt", () => {
    expect(apiStatLevel("score")).toBe("strokes_only")
    expect(apiStatLevel("score_putts")).toBe("strokes_and_putts")
    expect(apiStatLevel("full")).toBe("full")
  })
})
