import { describe, expect, it } from "vitest"

import type { Profil } from "../api"
import { isoTag } from "../format"
import { profilZuEinstellungen, profilZuFahrzeug, zusammenfuehren } from "./profilAdapter"

function tagVersetzt(tage: number): string {
  const d = new Date()
  d.setDate(d.getDate() + tage)
  return isoTag(d)
}

function beispielprofil(aenderung: Partial<Profil> = {}): Profil {
  return {
    fahrzeug: {
      fin: "WUAZZZF48PA902804",
      titel: "RS 4 Avant",
      zusatz: "competition",
      untertitel: "quattro · 331 kW",
      kennzeichen: "M AB 1234",
      tankvolumen_liter: 58,
    },
    einstellungen: {
      uebersichtsbild: "seitenansicht.webp",
      fahrten_pausenzeit_min: 15,
      smartdeal: { aktiv: true, laeuft_ab: null },
      oelwechsel_intervall: { modus: "hersteller", hersteller_km: 30000, hersteller_monate: 24 },
    },
    reifen: {
      aktiv: "sommer",
      anzugsmoment_nm: 140,
      saetze: { sommer: { km: 12000, marke: "Michelin" }, winter: { km: 8000 } },
    },
    steuer: { betrag_eur: 320 },
    ...aenderung,
  }
}

describe("profilZuEinstellungen", () => {
  it("liest die Fahrzeug- und Einstellungsfelder", () => {
    const e = profilZuEinstellungen(beispielprofil())
    expect(e.fahrzeugtitel).toBe("RS 4 Avant")
    expect(e.kennzeichen).toBe("M AB 1234")
    expect(e.tankvolumen).toBe(58)
    expect(e.pauseMin).toBe(15)
  })

  it("fällt auf sinnvolle Werte zurück, wenn Abschnitte fehlen", () => {
    const e = profilZuEinstellungen({})
    expect(e.tankvolumen).toBe(58)
    expect(e.pauseMin).toBe(15)
    expect(e.backupIntervall).toBe("aus")
  })
})

describe("SmartDeal-Gültigkeit", () => {
  it("gilt ohne Ablaufdatum, solange der Schalter an ist", () => {
    const f = profilZuFahrzeug(beispielprofil(), {})
    expect(f.smartdeal.aktiv).toBe(true)
  })

  it("gilt am Ablauftag noch — das Datum ist einschließlich", () => {
    const profil = beispielprofil()
    ;(profil.einstellungen as Record<string, unknown>)["smartdeal"] = {
      aktiv: true,
      laeuft_ab: isoTag(),
    }
    expect(profilZuFahrzeug(profil, {}).smartdeal.aktiv).toBe(true)
  })

  it("gilt am Folgetag nicht mehr", () => {
    const profil = beispielprofil()
    ;(profil.einstellungen as Record<string, unknown>)["smartdeal"] = {
      aktiv: true,
      laeuft_ab: tagVersetzt(-1),
    }
    expect(profilZuFahrzeug(profil, {}).smartdeal.aktiv).toBe(false)
  })

  it("bleibt aus, wenn der Schalter aus ist — auch bei gültigem Datum", () => {
    const profil = beispielprofil()
    ;(profil.einstellungen as Record<string, unknown>)["smartdeal"] = {
      aktiv: false,
      laeuft_ab: tagVersetzt(30),
    }
    expect(profilZuFahrzeug(profil, {}).smartdeal.aktiv).toBe(false)
  })
})

describe("profilZuFahrzeug mit Fahrzeugstatus", () => {
  it("übernimmt die Statuswerte unter den Namen des Backends", () => {
    const f = profilZuFahrzeug(beispielprofil(), {
      km: 48250,
      tankprozent: 62,
      reichweite_km: 385,
      gesichert: true,
      sicherheitscheck: [{ label: "Tür vorne links", ok: true, gruppe: "tueren_klappen" }],
    })
    expect(f.odo).toBe(48250)
    expect(f.odoBekannt).toBe(true)
    expect(f.tankPct).toBe(62)
    expect(f.reichweite).toBe(385)
    expect(f.gesichert).toBe(true)
    expect(f.sicherheitscheck).toHaveLength(1)
  })

  it("unterscheidet unbekannten Kilometerstand von null", () => {
    const f = profilZuFahrzeug(beispielprofil(), {})
    expect(f.odo).toBe(0)
    expect(f.odoBekannt).toBe(false)
  })

  it("übersetzt den aktiven Reifensatz in die Anzeigeform", () => {
    const profil = beispielprofil()
    ;(profil.reifen as Record<string, unknown>)["aktiv"] = "winter"
    expect(profilZuFahrzeug(profil, {}).reifen.aktiv).toBe("Winter")
  })
})

describe("zusammenfuehren", () => {
  it("schreibt geänderte Einstellungen zurück, ohne Unbekanntes zu verlieren", () => {
    const roh = beispielprofil({ technik: [{ gruppe: "Motor", posten: [["Hubraum", "2.9 V6"]] }] })
    const einstellungen = profilZuEinstellungen(roh)
    const fahrzeug = profilZuFahrzeug(roh, {})
    einstellungen.kennzeichen = "M XY 9999"

    const neu = zusammenfuehren(roh, einstellungen, fahrzeug)
    expect((neu.fahrzeug as Record<string, unknown>)["kennzeichen"]).toBe("M XY 9999")
    // Abschnitte, die die Oberfläche nicht anfasst, bleiben unverändert.
    expect(neu.technik).toEqual([{ gruppe: "Motor", posten: [["Hubraum", "2.9 V6"]] }])
  })

  it("schreibt den Reifen-Kilometerstand nie mit", () => {
    // Das Backend (reifenzaehler.py) schreibt km bei jeder Änderung des
    // Kilometerstands fort. Ein im Browser gehaltener älterer Stand darf das
    // nicht überschreiben.
    const roh = beispielprofil()
    const fahrzeug = profilZuFahrzeug(roh, {})
    fahrzeug.reifen.sommer.km = 1
    fahrzeug.reifen.sommer.marke = "Continental"

    const neu = zusammenfuehren(roh, profilZuEinstellungen(roh), fahrzeug)
    const saetze = (neu.reifen as Record<string, unknown>)["saetze"] as Record<
      string,
      Record<string, unknown>
    >
    expect(saetze["sommer"]?.["km"]).toBe(12000)
    expect(saetze["sommer"]?.["marke"]).toBe("Continental")
  })

  it("macht aus einem leeren Steuerdatum null statt einer leeren Zeichenkette", () => {
    const roh = beispielprofil()
    const fahrzeug = profilZuFahrzeug(roh, {})
    const neu = zusammenfuehren(roh, profilZuEinstellungen(roh), fahrzeug)
    expect((neu.steuer as Record<string, unknown>)["faellig"]).toBeNull()
  })
})
