"use client";

// Manuel 24'lük liste — Yapay Zeka'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 "@/types/yokatlas";
import { riskHesapla } from "@/lib/risk";
import { type TercihProfili } from "@/features/sihirbaz/sihirbaz-sabitler";
import { tercihProfiliOku } from "@/features/sihirbaz/sihirbaz-profil";
import {
  MANUEL_LISTE_MAX,
  dogrula,
  type ManuelKaynak,
  type ManuelTercih,
} from "./liste-dogrula";

// Doğrulama katmanı sunucu action'larıyla paylaşılır (bkz. dogrula.ts);
// mevcut import yolları kırılmasın diye buradan re-export edilir.
export { MANUEL_LISTE_MAX, type ManuelKaynak, type ManuelTercih };

const STORAGE_KEY = "kolaytercih.manuel-liste.v1";

// 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 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);
}

/** Senkron snapshot — giriş anı merge'inde sunucuya gönderilecek liste. */
export function listeOku(): ManuelTercih[] {
  yukle();
  return liste;
}

/**
 * Sunucudan dönen kanonik listeyi lokale birleştirir: lokal sıra korunur,
 * lokalde olmayan sunucu kayıtları sona eklenir, 24 sınırı aşılmaz.
 * (Çakışmada localStorage kazanır — PRD C1 kuralı.)
 */
export function sunucuylaBirlestir(sunucuItems: ManuelTercih[]): ManuelTercih[] {
  yukle();
  const mevcut = new Set(liste.map((t) => t.id));
  const ekler = sunucuItems.filter((t) => !mevcut.has(t.id));
  if (ekler.length === 0) return liste;
  liste = [...liste, ...ekler].slice(0, MANUEL_LISTE_MAX);
  kaydet();
  yayinla();
  return liste;
}

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();
}
