/**
 * Eigene Ölwechsel-Prognose. Portiert aus `oelwechselPrognose()` im alten
 * Panel.
 *
 * Die Rechnung beginnt bewusst neu ab dem letzten tatsächlich durchgeführten
 * Ölwechsel — der allgemeine Langzeitdurchschnitt seit dem allerersten
 * Servicebucheintrag wäre dafür zu träge. Aus km und Tagen seit dem letzten
 * Wechsel ergibt sich die aktuelle Fahrleistung pro Tag; hochgerechnet auf die
 * verbleibenden km bis zum eingestellten Intervall ergibt das ein Datum,
 * gedeckelt auf spätestens das Zeitlimit des Intervalls.
 */

import type { Fahrzeug } from "./profilAdapter"

const TAG_MS = 86_400_000

export interface Oelprognose {
  /** ISO-Tagesdatum. */
  datum: string
  restKm: number
  kmProTag: number
  /** Die Zeitgrenze hat gegriffen, nicht die Kilometergrenze. */
  durchZeitlimit: boolean
}

interface Buchhaltung {
  datum?: string
  km?: number
  art?: string
}

function monatePlus(isoDatum: string, monate: number): string {
  const d = new Date(isoDatum)
  if (Number.isNaN(d.getTime())) return isoDatum
  d.setMonth(d.getMonth() + monate)
  return d.toISOString().slice(0, 10)
}

/** Der jüngste Servicebucheintrag, dessen Art auf einen Ölwechsel hindeutet. */
export function letzterOelwechsel(buch: readonly Buchhaltung[]): Buchhaltung | null {
  const treffer = buch
    .filter((e) => typeof e.art === "string" && /öl|oel/i.test(e.art) && e.datum && e.km != null)
    .sort((a, b) => String(b.datum).localeCompare(String(a.datum)))
  return treffer[0] ?? null
}

export function oelwechselPrognose(
  fahrzeug: Fahrzeug,
  buch: readonly Buchhaltung[],
  jetzt = new Date(),
): Oelprognose | null {
  if (!fahrzeug.odoBekannt) return null
  const letzter = letzterOelwechsel(buch)
  if (!letzter?.datum || letzter.km == null) return null

  const oel = fahrzeug.oel
  const intervallKm =
    oel.modus === "hersteller"
      ? (oel.herstellerKm ?? 0)
      : Math.min(oel.km ?? Infinity, oel.herstellerKm ?? Infinity)
  const intervallMonate =
    oel.modus === "hersteller"
      ? (oel.herstellerMonate ?? 0)
      : Math.min(oel.monate ?? Infinity, oel.herstellerMonate ?? Infinity)

  if (!Number.isFinite(intervallKm) || intervallKm <= 0) return null

  const zielKm = letzter.km + intervallKm
  const restKm = Math.max(0, zielKm - fahrzeug.odo)
  const kappDatum = monatePlus(letzter.datum, Number.isFinite(intervallMonate) ? intervallMonate : 24)

  if (restKm <= 0) {
    return { datum: jetzt.toISOString().slice(0, 10), restKm: 0, kmProTag: 0, durchZeitlimit: false }
  }

  const tageSeit = (jetzt.getTime() - new Date(letzter.datum).getTime()) / TAG_MS
  const kmSeit = fahrzeug.odo - letzter.km

  // Ohne belastbare Fahrleistung (direkt nach dem Wechsel) gibt es keine
  // seriöse Kilometerprognose — dann gilt das Zeitlimit.
  if (tageSeit <= 0 || kmSeit <= 0) {
    return { datum: kappDatum, restKm, kmProTag: 0, durchZeitlimit: true }
  }

  const kmProTag = kmSeit / tageSeit
  const tageBisZiel = restKm / kmProTag
  const ausKm = new Date(jetzt.getTime() + tageBisZiel * TAG_MS).toISOString().slice(0, 10)

  const durchZeitlimit = kappDatum < ausKm
  return {
    datum: durchZeitlimit ? kappDatum : ausKm,
    restKm,
    kmProTag,
    durchZeitlimit,
  }
}
