"use client";

// Manuel 24'lük liste — AI'dan bağımsız, kullanıcının tablodan "+" ile kendi
// kurduğu tercih listesi. Kaynak tek: bu modüldeki harici store. Navbar rozeti,
// çekmece ve program tablosu aynı store'a abone olur; kalıcılık localStorage'ta
// (girişsiz kullanıcı da liste kurabilsin diye sunucuya yazmıyoruz).

import { useSyncExternalStore } from "react";
import type { Program } from "@/lib/db";
import { riskHesapla, type RiskSeviyesi } from "@/lib/risk";
import {
  tercihProfiliOku,
  type TercihProfili,
} from "@/lib/sihirbaz";

export const MANUEL_LISTE_MAX = 24;
const STORAGE_KEY = "kolaytercih.manuel-liste.v1";

export type ManuelKaynak = "sonuc" | "bolum" | "universite";

export type ManuelTercih = {
  /** yokatlas program id'si */
  id: string;
  isim: string;
  universite: string;
  il: string | null;
  unitur: string | null;
  tur: string | null;
  efektifSira: number | null;
  /** Ekleme / profil anındaki aday sıralamasına göre risk */
  risk: RiskSeviyesi | null;
  kaynak?: ManuelKaynak;
};

// SSR snapshot'ı: her çağrıda aynı referans dönmeli, yoksa React döngüye girer
const BOS_LISTE: ManuelTercih[] = [];

let liste: ManuelTercih[] = BOS_LISTE;
let cekmeceAcik = false;
let yuklendi = false;

const dinleyiciler = new Set<() => void>();

function yayinla() {
  for (const cb of dinleyiciler) cb();
}

function kaydet() {
  try {
    localStorage.setItem(STORAGE_KEY, JSON.stringify(liste));
  } catch {}
}

function dogrula(ham: unknown): ManuelTercih[] {
  if (!Array.isArray(ham)) return [];
  const sonuc: ManuelTercih[] = [];
  for (const t of ham) {
    if (typeof t !== "object" || t === null) continue;
    const kayit = t as Record<string, unknown>;
    if (typeof kayit.id !== "string" || typeof kayit.isim !== "string") continue;
    const risk: RiskSeviyesi | null =
      kayit.risk === "guvenli" ||
      kayit.risk === "az-riskli" ||
      kayit.risk === "riskli"
        ? kayit.risk
        : null;
    const kaynak: ManuelKaynak | undefined =
      kayit.kaynak === "sonuc" ||
      kayit.kaynak === "bolum" ||
      kayit.kaynak === "universite"
        ? kayit.kaynak
        : undefined;
    sonuc.push({
      id: kayit.id,
      isim: kayit.isim,
      universite: typeof kayit.universite === "string" ? kayit.universite : "",
      il: typeof kayit.il === "string" ? kayit.il : null,
      unitur: typeof kayit.unitur === "string" ? kayit.unitur : null,
      tur: typeof kayit.tur === "string" ? kayit.tur : null,
      efektifSira:
        typeof kayit.efektifSira === "number" &&
        Number.isFinite(kayit.efektifSira)
          ? kayit.efektifSira
          : null,
      risk,
      kaynak,
    });
    if (sonuc.length >= MANUEL_LISTE_MAX) break;
  }
  return sonuc;
}

function yukle() {
  if (yuklendi || typeof window === "undefined") return;
  yuklendi = true;
  try {
    const ham = localStorage.getItem(STORAGE_KEY);
    if (ham) liste = dogrula(JSON.parse(ham));
  } catch {}
  // Başka sekmede yapılan değişiklikleri de yansıt
  window.addEventListener("storage", (e) => {
    if (e.key !== STORAGE_KEY) return;
    try {
      liste = e.newValue ? dogrula(JSON.parse(e.newValue)) : [];
      yayinla();
    } catch {}
  });
}

function abone(cb: () => void) {
  dinleyiciler.add(cb);
  if (!yuklendi) {
    // İlk client abonesi: storage'ı oku ve snapshot'ı tazele
    yukle();
    queueMicrotask(yayinla);
  }
  return () => {
    dinleyiciler.delete(cb);
  };
}

export function useManuelListe(): ManuelTercih[] {
  return useSyncExternalStore(
    abone,
    () => liste,
    () => BOS_LISTE,
  );
}

export function useCekmeceAcik(): boolean {
  return useSyncExternalStore(
    abone,
    () => cekmeceAcik,
    () => false,
  );
}

export function listedeMi(id: string): boolean {
  return liste.some((t) => t.id === id);
}

export function efektifSiraAl(
  p: Pick<Program, "sira2025" | "sira2024">,
): number | null {
  return p.sira2025 ?? p.sira2024 ?? null;
}

/** Program satırını manuel liste kaydına çevirir. */
export function programdanManuelTercih(
  p: Pick<
    Program,
    | "id"
    | "isim"
    | "universite"
    | "il"
    | "unitur"
    | "tur"
    | "sira2025"
    | "sira2024"
  >,
  adaySira?: number | null,
  kaynak: ManuelKaynak = "sonuc",
): ManuelTercih {
  const taban = efektifSiraAl(p);
  return {
    id: p.id,
    isim: p.isim,
    universite: p.universite,
    il: p.il,
    unitur: p.unitur ?? null,
    tur: p.tur,
    efektifSira: taban,
    risk:
      adaySira != null && Number.isFinite(adaySira)
        ? riskHesapla(taban, adaySira)
        : null,
    kaynak,
  };
}

/** Profil sırasına göre listedeki riskleri yeniden hesaplar (program silmez). */
export function riskleriYenile(profil?: TercihProfili | null) {
  yukle();
  const p = profil ?? tercihProfiliOku();
  if (!p) return;
  liste = liste.map((t) => ({
    ...t,
    risk: riskHesapla(t.efektifSira, p.sira),
  }));
  kaydet();
  yayinla();
}

/** Listeye ekler; doluysa veya zaten varsa false döner. */
export function ekle(tercih: ManuelTercih): boolean {
  yukle();
  if (liste.length >= MANUEL_LISTE_MAX || listedeMi(tercih.id)) return false;
  const profil = tercihProfiliOku();
  const kayit: ManuelTercih = {
    ...tercih,
    risk:
      profil != null
        ? riskHesapla(tercih.efektifSira, profil.sira)
        : tercih.risk,
  };
  liste = [...liste, kayit];
  kaydet();
  yayinla();
  return true;
}

export function cikar(id: string) {
  liste = liste.filter((t) => t.id !== id);
  kaydet();
  yayinla();
}

/** Sürükle-bırak sonrası yeni sıra (motion Reorder'dan gelir) */
export function yenidenSirala(yeni: ManuelTercih[]) {
  liste = yeni;
  kaydet();
  yayinla();
}

export function temizle() {
  liste = [];
  kaydet();
  yayinla();
}

export function cekmeceAc() {
  cekmeceAcik = true;
  yayinla();
}

export function cekmeceKapat() {
  cekmeceAcik = false;
  yayinla();
}

export function cekmeceDegistir() {
  cekmeceAcik = !cekmeceAcik;
  yayinla();
}
