// Kayıtlı listenin üretildiği tercihler (rapor params) ile kullanıcının şu
// anki tercih profilini karşılaştırır. /listem başlığındaki "Tercihlerin
// değişmiş" butonu ve açtığı güncelleme modalı bu farktan doğar.
//
// İzomorfik: yalnızca tip ve etiket sabitlerine bağlı — hem client bileşeni
// hem sunucu tarafı tüketebilir.
//
// Eski akışla üretilmiş raporlarda sihirbaz alanları (kategoriler/iller/
// universiteTipi/oncelikler) hiç yok. Olmayan alan "değişmiş" sayılmaz:
// kıyaslanacak bir değer yokken kullanıcıyı 3 kredilik güncellemeye
// çağırmak dürüst olmaz. Sıralama ve puan türü her raporda dolu olduğundan
// onlar her zaman kıyaslanır.

import {
  PUAN_TURU_ETIKET,
  UNIVERSITE_TIPI_ETIKET,
  type TercihProfili,
} from "@/features/sihirbaz/sihirbaz-sabitler";
import type { RaporParams } from "./types/rapor";

export type FarkAlani =
  | "sira"
  | "tur"
  | "kategoriler"
  | "iller"
  | "universiteTipi"
  | "oncelikler";

export const FARK_ETIKET: Record<FarkAlani, string> = {
  sira: "başarı sıralaman",
  tur: "puan türün",
  kategoriler: "ilgi alanların",
  iller: "şehir tercihlerin",
  universiteTipi: "devlet/vakıf tercihin",
  oncelikler: "önceliklerin",
};

// Sıra bağımsız küme kıyası: sihirbaz seçimleri tekrarsız olarak doğrulanır
// (bkz. sihirbazDogrula), aynı seçimlerin farklı sırayla kaydedilmesi
// "değişiklik" değildir.
function kumeFarkli(
  eski: readonly string[] | undefined,
  yeni: readonly string[],
): boolean {
  if (!eski) return false;
  if (eski.length !== yeni.length) return true;
  const kume = new Set(eski);
  return yeni.some((x) => !kume.has(x));
}

function liste(degerler: readonly string[] | undefined): string {
  return degerler && degerler.length > 0 ? degerler.join(", ") : "—";
}

export function tercihFarki(
  params: RaporParams,
  profil: TercihProfili,
): FarkAlani[] {
  const farklar: FarkAlani[] = [];
  const s = profil.secimler;

  if (Math.round(params.sira) !== Math.round(profil.sira)) farklar.push("sira");
  if (params.tur !== profil.tur) farklar.push("tur");
  if (kumeFarkli(params.kategoriler, s.kategoriler)) farklar.push("kategoriler");
  if (kumeFarkli(params.iller, s.iller)) farklar.push("iller");
  if (
    params.universiteTipi !== undefined &&
    params.universiteTipi !== s.universiteTipi
  ) {
    farklar.push("universiteTipi");
  }
  if (kumeFarkli(params.oncelikler, s.oncelikler)) farklar.push("oncelikler");

  return farklar;
}

export type FarkSatiri = { alan: FarkAlani; etiket: string; eski: string; yeni: string };

/** Değişen her alanın eski → yeni değeri; uyarıda tek tek gösterilir. */
export function farkSatirlari(
  params: RaporParams,
  profil: TercihProfili,
  farklar: FarkAlani[],
): FarkSatiri[] {
  const s = profil.secimler;
  const sayi = (n: number) => Math.round(n).toLocaleString("tr-TR");

  return farklar.map((alan) => {
    const ortak = { alan, etiket: FARK_ETIKET[alan] };
    switch (alan) {
      case "sira":
        return { ...ortak, eski: `${sayi(params.sira)}.`, yeni: `${sayi(profil.sira)}.` };
      case "tur":
        return {
          ...ortak,
          eski: PUAN_TURU_ETIKET[params.tur] ?? params.tur,
          yeni: PUAN_TURU_ETIKET[profil.tur] ?? profil.tur,
        };
      case "kategoriler":
        return { ...ortak, eski: liste(params.kategoriler), yeni: liste(s.kategoriler) };
      case "iller":
        return { ...ortak, eski: liste(params.iller), yeni: liste(s.iller) };
      case "universiteTipi":
        return {
          ...ortak,
          eski: UNIVERSITE_TIPI_ETIKET[params.universiteTipi ?? "farketmez"],
          yeni: UNIVERSITE_TIPI_ETIKET[s.universiteTipi],
        };
      case "oncelikler":
        return { ...ortak, eski: liste(params.oncelikler), yeni: liste(s.oncelikler) };
    }
  });
}
