import { useEffect, useState } from "preact/hooks";

type Note = { numEtud: number; idModule: string; note: number };
type UE = { id: number; nom: string };
type UEModule = {
  idModule: string;
  idUE: number;
  idPromo: string;
  coeff: number;
};
type Module = { id: string; nom: string };
type Ajustement = { numEtud: number; idUE: number; valeur: number };

type Props = {
  numEtud: number | null;
  prenom: string;
};

function scoreClass(score: number | null): string {
  if (score === null) return "score-none";
  return score >= 10 ? "score-good" : "score-warn";
}

function avgClass(avg: number | null): string {
  if (avg === null) return "";
  return avg >= 10 ? "avg-good" : "avg-warn";
}

export default function NotesView({ numEtud, prenom }: Props) {
  const [notes, setNotes] = useState<Note[]>([]);
  const [ues, setUes] = useState<UE[]>([]);
  const [ueModules, setUeModules] = useState<UEModule[]>([]);
  const [modules, setModules] = useState<Module[]>([]);
  const [ajustements, setAjustements] = useState<Ajustement[]>([]);
  const [promos, setPromos] = useState<string[]>([]);
  const [activePromo, setActivePromo] = useState<string | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (numEtud === null) {
      setLoading(false);
      return;
    }

    async function load() {
      try {
        const [notesRes, uesRes, ueModRes, modRes, ajRes] = await Promise.all([
          fetch(`/notes/api/notes?numEtud=${numEtud}`),
          fetch("/notes/api/ues"),
          fetch("/notes/api/ue-modules"),
          fetch("/admin/api/modules"),
          fetch(`/notes/api/ajustements?numEtud=${numEtud}`),
        ]);

        if (!notesRes.ok || !uesRes.ok || !ueModRes.ok) {
          throw new Error("Erreur lors du chargement");
        }

        const [notesData, uesData, ueModData, modData, ajData] = await Promise
          .all([
            notesRes.json(),
            uesRes.json(),
            ueModRes.json(),
            modRes.ok ? modRes.json() : [],
            ajRes.ok ? ajRes.json() : [],
          ]);

        setNotes(notesData);
        setUes(uesData);
        setUeModules(ueModData);
        setModules(modData);
        setAjustements(ajData);

        // Derive promos from UE-modules for this student's notes
        const noteModuleIds = new Set(notesData.map((n: Note) => n.idModule));
        const relevantPromos = [
          ...new Set(
            ueModData
              .filter((um: UEModule) => noteModuleIds.has(um.idModule))
              .map((um: UEModule) => um.idPromo),
          ),
        ] as string[];

        setPromos(relevantPromos);
        if (relevantPromos.length > 0) setActivePromo(relevantPromos[0]);
      } catch (e) {
        setError(e instanceof Error ? e.message : "Erreur inconnue");
      } finally {
        setLoading(false);
      }
    }

    load();
  }, [numEtud]);

  if (numEtud === null) {
    return (
      <div class="page-content">
        <p class="state-empty">
          Bonjour {prenom}{" "}
          — aucun dossier étudiant n'est associé à votre compte.
        </p>
      </div>
    );
  }

  if (loading) {
    return (
      <div class="page-content">
        <p class="state-loading">Chargement…</p>
      </div>
    );
  }

  if (error) {
    return (
      <div class="page-content">
        <p class="state-error">{error}</p>
      </div>
    );
  }

  // Filter UE-modules by active promo
  const filteredUeModules = activePromo
    ? ueModules.filter((um) => um.idPromo === activePromo)
    : ueModules;

  // Group UE-modules by UE
  const ueIds = [...new Set(filteredUeModules.map((um) => um.idUE))];

  const moduleMap = Object.fromEntries(modules.map((m) => [m.id, m]));
  const noteMap = Object.fromEntries(
    notes.map((n) => [n.idModule, n.note]),
  );
  const ajMap = Object.fromEntries(
    ajustements.map((a) => [a.idUE, a.valeur]),
  );

  return (
    <div class="page-content">
      {promos.length > 1 && (
        <div class="tabs">
          {promos.map((p) => (
            <button
              type="button"
              key={p}
              class={`tab-btn${activePromo === p ? " active" : ""}`}
              onClick={() => setActivePromo(p)}
            >
              {p}
            </button>
          ))}
        </div>
      )}

      {ueIds.length === 0 && (
        <p class="state-empty">Aucune note disponible pour cette période.</p>
      )}

      {ueIds.map((ueId) => {
        const ue = ues.find((u) => u.id === ueId);
        if (!ue) return null;

        const ueModsForUE = filteredUeModules.filter((um) => um.idUE === ueId);
        let weightedSum = 0;
        let coveredCoeff = 0;
        ueModsForUE.forEach((um) => {
          const note = noteMap[um.idModule];
          if (note !== undefined) {
            weightedSum += note * um.coeff;
            coveredCoeff += um.coeff;
          }
        });

        const avg = coveredCoeff > 0 ? weightedSum / coveredCoeff : null;
        const ajustement = ajMap[ueId] ?? null;
        const finalAvg = avg !== null && ajustement !== null
          ? avg + ajustement
          : avg;

        return (
          <div key={ueId} class="ue-card">
            <div class="ue-card-header">
              <p class="ue-card-title">UE : {ue.nom}</p>
              {finalAvg !== null && (
                <p class={`ue-card-avg ${avgClass(finalAvg)}`}>
                  Moyenne : {finalAvg.toFixed(2)}/20
                  {ajustement !== null && ajustement !== 0 && (
                    <span>
                      {" "}
                      (ajustement : {ajustement > 0 ? "+" : ""}
                      {ajustement})
                    </span>
                  )}
                </p>
              )}
              {finalAvg === null && (
                <p class="ue-card-avg avg-warn">Notes non disponibles</p>
              )}
            </div>

            {ueModsForUE.map((um) => {
              const mod = moduleMap[um.idModule];
              const note = noteMap[um.idModule] ?? null;
              return (
                <div key={um.idModule} class="ue-module-row">
                  <span class="ue-module-name">
                    {mod ? mod.id : um.idModule} —{" "}
                    {mod ? mod.nom : "Module inconnu"} (coef {um.coeff})
                  </span>
                  <span class={`score-chip ${scoreClass(note)}`}>
                    {note !== null ? `${note}/20` : "—"}
                  </span>
                </div>
              );
            })}
          </div>
        );
      })}
    </div>
  );
}
