import { ActionFormData, ModalFormData } from "@minecraft/server-ui";
import { ENTRIES } from "./entries.js";
import { hasSeen, hasSeenVariant, hasFull, hasAdvanced } from "./storage.js";
import { getGlobalCompletion } from "./progressUtils.js";
import { getEntryCompletion } from "./progressUtils.js";


/* ===========================
   State (por jugador)
=========================== */
const filterStateByPlayer = new Map(); // player.id -> { tags:Set<string>, sort:number }

function getState(player) {
  let st = filterStateByPlayer.get(player.id);
  if (!st) {
    st = { tags: new Set(), sort: 0 }; // 0 A-Z, 1 vistos primero, 2 no vistos primero
    filterStateByPlayer.set(player.id, st);
  }
  return st;
}

function setState(player, st) {
  filterStateByPlayer.set(player.id, st);
}

/* ===========================
   Helpers (efectos/variant)
=========================== */
function romanAmp(amp0based) {
  const n = (amp0based ?? 0) + 1;
  const map = ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X"];
  return map[n - 1] ?? String(n);
}

function getEffectsForVariant(entry, variantId) {
  const byVariant = entry?.bestiaryInfo?.playerEffects?.byVariant;
  if (!Array.isArray(byVariant)) return [];

  const row = byVariant.find((r) => r.variantId === variantId);
  const effects = row?.effects;
  return Array.isArray(effects) ? effects : [];
}

function buildVariantBody(player, entry, variant) {
  const rawtext = [];

  if (entry?.bestiaryInfo?.effectsNoteKey) {
    rawtext.push({ translate: entry.bestiaryInfo.effectsNoteKey });
  }

  const effects = getEffectsForVariant(entry, variant.id);
  if (effects.length > 0) {
    rawtext.push({ text: "\n\n" });
    rawtext.push({ translate: "dungeon.langcode.bestiary.effects_header" });

    for (const ef of effects) {
      rawtext.push({ text: "\n- " });
      rawtext.push(
        ef.effectKey ? { translate: ef.effectKey } : { text: "?" }
      );

      if (typeof ef.amp === "number") {
        rawtext.push({ text: ` ${romanAmp(ef.amp)}` });
      }
    }
  }

  return { rawtext };
}

/* ===========================
   Helpers: tags + filtering
=========================== */

// Tags globales disponibles (de ENTRIES)
function collectAllTags() {
  const set = new Set();
  for (const e of ENTRIES) {
    if (Array.isArray(e.tags)) for (const t of e.tags) set.add(String(t));
  }
  return [...set].sort((a, b) => a.localeCompare(b));
}
const ALL_TAGS = collectAllTags();

function matchesTags(entry, selectedTagsSet) {
  if (!selectedTagsSet || selectedTagsSet.size === 0) return true;
  const tags = Array.isArray(entry.tags) ? entry.tags : [];
  // AND: debe contener TODAS las tags seleccionadas
  for (const t of selectedTagsSet) {
    if (!tags.includes(t)) return false;
  }
  return true;
}

function applyFilters(player) {
  const st = getState(player);

  const list = ENTRIES.filter((e) => matchesTags(e, st.tags));

  list.sort((a, b) => {
    // 1) Prioridad vistos/no vistos
    if (st.sort === 1 || st.sort === 2) {
      const aSeen = hasSeen(player, a.id) ? 1 : 0;
      const bSeen = hasSeen(player, b.id) ? 1 : 0;

      // st.sort === 1 => vistos primero (1 arriba)
      // st.sort === 2 => no vistos primero (0 arriba)
      const dir = st.sort === 1 ? -1 : 1; // invierte el criterio
      if (aSeen !== bSeen) return (aSeen - bSeen) * dir;
    }

    // 2) Empate o A–Z puro
    // Si quieres por nombre traducido real NO se puede aquí; usamos id estable
    return String(a.id).localeCompare(String(b.id));
  });

  return list;
}

/* ===========================
   UI: Filtrar por tags
=========================== */

function showBestiaryFilters(player, onDone) {
  const st = getState(player);

  const sortKey =
    st.sort === 1
      ? "dungeon.langcode.bestiary.sort_seen"
      : st.sort === 2
        ? "dungeon.langcode.bestiary.sort_unseen"
        : "dungeon.langcode.bestiary.sort_az";

  const tagsText =
    st.tags.size
      ? [...st.tags].join(", ")
      : "";

  const form = new ActionFormData()
    .title({ translate: "dungeon.langcode.bestiary.filter_title" })
    .body({
      rawtext: [
        { translate: "dungeon.langcode.bestiary.filter_sort_label" },
        { text: " " },
        { translate: sortKey },
        { text: "\n" },
        { translate: "dungeon.langcode.bestiary.filter_tags_label" },
        { text: ` ${tagsText}` }
      ]
    });

  form.button({ translate: "dungeon.langcode.bestiary.filter_sort_button" });
  form.button({ translate: "dungeon.langcode.bestiary.filter_tags_button" });
  form.button({ translate: "dungeon.langcode.bestiary.filter_clear_button" });
  form.button({ translate: "dungeon.langcode.guide.button.back" });

  form.show(player).then((res) => {
    if (res.canceled) return onDone(player);

    switch (res.selection) {
      case 0: return showBestiarySortPicker(player, () => showBestiaryFilters(player, onDone));
      case 1: return showBestiaryTagPicker(player, () => showBestiaryFilters(player, onDone));
      case 2: {
        setState(player, { sort: 0, tags: new Set() });
        return showBestiaryFilters(player, onDone);
      }
      default: return onDone(player);
    }
  });
}

function showBestiarySortPicker(player, back) {
  const st = getState(player);

  const form = new ActionFormData()
    .title({ translate: "dungeon.langcode.bestiary.sort_title" })
    .body({ translate: "dungeon.langcode.bestiary.sort_body" });

  form.button({
    rawtext: [
      { text: st.sort === 0 ? "§a✓§r " : "" },
      { translate: "dungeon.langcode.bestiary.sort_az" }
    ]
  });

  form.button({
    rawtext: [
      { text: st.sort === 1 ? "§a✓§r " : "" },
      { translate: "dungeon.langcode.bestiary.sort_seen" }
    ]
  });

  form.button({
    rawtext: [
      { text: st.sort === 2 ? "§a✓§r " : "" },
      { translate: "dungeon.langcode.bestiary.sort_unseen" }
    ]
  });

  form.button({ translate: "dungeon.langcode.guide.button.back" });

  form.show(player).then((res) => {
    if (res.canceled) return back(player);
    if (res.selection === 3) return back(player);

    setState(player, { sort: res.selection, tags: st.tags });
    back(player);
  });
}

function showBestiaryTagPicker(player, back) {
  const st = getState(player);

  const form = new ActionFormData()
    .title({ translate: "dungeon.langcode.bestiary.tags_title" })
    .body({ translate: "dungeon.langcode.bestiary.tags_body" });

  for (const tag of ALL_TAGS) {
    const active = st.tags.has(tag);

    form.button({
      rawtext: [
        { text: active ? "§a[x]§r " : "§7[ ]§r " },
        { translate: `dungeon.langcode.tag.${tag}` }
      ]
    });
  }

  form.button({ translate: "dungeon.langcode.guide.button.back" });

  form.show(player).then((res) => {
    if (res.canceled) return back(player);

    const backIndex = ALL_TAGS.length;
    if (res.selection === backIndex) return back(player);

    const tag = ALL_TAGS[res.selection];
    if (!tag) return back(player);

    const newTags = new Set(st.tags);
    if (newTags.has(tag)) newTags.delete(tag);
    else newTags.add(tag);

    setState(player, { sort: st.sort, tags: newTags });
    showBestiaryTagPicker(player, back);
  });
}

/* ===========================
   LISTA PRINCIPAL (con botón Filtros)
=========================== */

export function showBestiary(player, backCallback) {
  const filtered = applyFilters(player);
  const st = getState(player);
  const globalPercent = getGlobalCompletion(player);

  const form = new ActionFormData()
    .title({ translate: "dungeon.langcode.guide.button.bestiary" })
    .body({
      rawtext: [
        { translate: "dungeon.langcode.bestiary.body" },
        { text: "\n\n§6Completion: §f" + globalPercent + "/100" },
        { text: "\n\n" },
        { text: `Tags: ${st.tags.size ? [...st.tags].join(", ") : "()"}` }
      ]
    });

  // 0) botón filtros
  form.button({ translate: "dungeon.langcode.bestiary.filter_title" }, "textures/ui/icon_setting");

  // 1..N) entries filtradas
  for (const entry of filtered) {
    const seen = hasSeen(player, entry.id);
    const percent = getEntryCompletion(player, entry);

    const label = seen
      ? {
        rawtext: [
          { translate: entry.nameKey },
          { text: ` §2${percent}/100` }
        ]
      }
      : { text: "????" };

    const icon = seen
      ? (entry.icon ?? "textures/ui/bestiary/unknown")
      : (entry.lockedIcon ?? "textures/ui/bestiary/unknown");

    form.button(label, icon);
  }

  // último: back
  form.button({ translate: "dungeon.langcode.guide.button.back" });

  form.show(player).then((res) => {
    if (res.canceled) return;

    const sel = res.selection;

    // Filtros
    if (sel === 0) {
      return showBestiaryFilters(player, () => showBestiary(player, backCallback));
    }

    const backIndex = 1 + filtered.length;
    if (sel === backIndex) return backCallback(player);

    const entryIndex = sel - 1;
    const entry = filtered[entryIndex];
    if (!entry) return;

    showBestiaryEntry(player, entry, () => showBestiary(player, backCallback));
  });
}

/* ===========================
   DETALLE DEL MOB (solo basic)
=========================== */

export function showBestiaryEntry(player, entry, backCallback) {
  const entryLocked = !hasSeen(player, entry.id);

  const basicKey = entry?.descriptions?.basic ?? "dungeon.langcode.bestiary.no_desc";

  const form = new ActionFormData()
    .title(entryLocked ? { text: "????" } : { translate: entry.nameKey })
    .body(
      entryLocked
        ? { translate: "dungeon.langcode.bestiary.locked" }
        : (() => {
          const raw = [];

          // BASIC (siempre que esté visto)
          raw.push({ translate: basicKey });

          // FULL solo si desbloqueado
          if (hasFull(player, entry.id) && entry.descriptions?.full) {
            raw.push({ text: "\n\n" });
            raw.push({ translate: entry.descriptions.full });
          }

          // ADVANCED solo si desbloqueado
          if (hasAdvanced(player, entry.id) && entry.descriptions?.advanced) {
            raw.push({ text: "\n\n" });
            raw.push({ translate: entry.descriptions.advanced });
          }

          // Nota de efectos (solo si al menos basic)
          if (entry.bestiaryInfo?.effectsNoteKey) {
            raw.push({ text: "\n\n" });
            raw.push({ translate: entry.bestiaryInfo.effectsNoteKey });
          }

          return { rawtext: raw };
        })()
    )

  const variants = (!entryLocked && Array.isArray(entry.variants)) ? entry.variants : [];

  for (const v of variants) {
    const vSeen = hasSeenVariant(player, entry.id, v.id);

    form.button(
      vSeen ? { translate: v.nameKey } : { text: "????" },
      vSeen ? (v.icon ?? entry.icon) : (entry.lockedIcon ?? "textures/ui/bestiary/unknown")
    );
  }

  form.button({ translate: "dungeon.langcode.guide.button.back" });

  form.show(player).then((res) => {
    if (res.canceled) return;

    const sel = res.selection;
    const backIndex = variants.length;
    if (sel === backIndex) return backCallback(player);

    const v = variants[sel];
    if (!v) return;

    // si no la ha visto, no abrir detalle
    if (!hasSeenVariant(player, entry.id, v.id)) return;

    return showBestiaryVariant(
      player,
      entry,
      v,
      () => showBestiaryEntry(player, entry, backCallback)
    );
  });
}

/* ===========================
   DETALLE DE VARIANTE (basic + efectos SOLO de esa variante)
=========================== */

function showBestiaryVariant(player, entry, variant, backCallback) {
  const locked = !hasSeen(player, entry.id);

  const form = new ActionFormData()
    .title({ translate: variant.nameKey })
    .body(
      locked
        ? { translate: "dungeon.langcode.bestiary.locked" }
        : buildVariantBody(player, entry, variant)
    );

  form.button({ translate: "dungeon.langcode.guide.button.back" });

  form.show(player).then((res) => {
    if (res.canceled) return;
    backCallback(player);
  });
}