const SITE = "https://hiroplay.lat";
const input = document.getElementById("searchInput");
const results = document.getElementById("results");
const suggestions = document.getElementById("suggestions");
const status = document.getElementById("indexStatus");
const modal = document.getElementById("analysisModal");
const analysis = document.getElementById("analysisContent");
const controls = document.getElementById("catalogControls");
const pagination = document.getElementById("pagination");
const backHome = document.getElementById("backHome");
let timer = 0,
  currentFilter = "all",
  currentPage = 1,
  searchMode = false,
  lastSuggestions = [];
const request = (message, ms = 30000) =>
  Promise.race([
    chrome.runtime.sendMessage(message),
    new Promise((resolve) =>
      setTimeout(
        () =>
          resolve({
            ok: false,
            error: "La solicitud tardó demasiado. Intenta nuevamente.",
          }),
        ms,
      ),
    ),
  ]);

document.getElementById("catalogButton").onclick = () =>
  chrome.runtime.sendMessage({ type: "OPEN_USER_CATALOG" });
const refreshButton = document.createElement("button"),
  refreshOverlay = document.createElement("div");
refreshButton.id = "refreshButton";
refreshButton.textContent = "↻ Cargar contenido nuevamente";
document.getElementById("catalogButton").before(refreshButton);
refreshOverlay.className = "refresh-overlay";
refreshOverlay.hidden = true;
refreshOverlay.innerHTML =
  "<div><i></i><b>Actualizando el catálogo</b><p>Espera mientras sincronizamos la copia más reciente de HIRO PLAY. Tus guardados y reproducciones no se borrarán.</p></div>";
document.body.append(refreshOverlay);
refreshButton.onclick = async () => {
  refreshOverlay.hidden = false;
  const response = await request({ type: "REFRESH_EXPLORE_CATALOG" }, 60000);
  refreshOverlay.hidden = true;
  status.textContent = response?.ok
    ? `Actualización completada · ${response.movieCount || 0} películas · ${response.seriesCount || 0} series`
    : response?.error ||
      "No se pudo actualizar; conservamos la copia anterior.";
  if (response?.ok) loadPage(1);
};
document.getElementById("closeAnalysis").onclick = () =>
  modal.classList.remove("open");
modal.addEventListener("click", (event) => {
  if (event.target === modal) modal.classList.remove("open");
});

const fallbackPoster = (container) => {
  const span = document.createElement("span");
  span.textContent = "▶";
  container.append(span);
};
function card(item, small = false) {
  const article = document.createElement("article");
  article.className = small ? "suggestion" : "result";
  const poster = document.createElement("div");
  poster.className = small ? "" : "poster";
  if (item.image) {
    const image = document.createElement("img");
    image.src = item.image;
    image.alt = "";
    image.onerror = () => {
      image.remove();
      fallbackPoster(poster);
    };
    poster.append(image);
  } else fallbackPoster(poster);
  const copy = document.createElement("div"),
    title = document.createElement("b"),
    type = document.createElement("small");
  title.textContent = item.title || "Contenido";
  type.textContent = item.type || "Contenido";
  copy.append(title, type);
  if (small) {
    const arrow = document.createElement("span");
    arrow.textContent = "Ver";
    article.append(poster, copy, arrow);
  } else article.append(poster, copy);
  article.onclick = () => analyzeItem(item);
  return article;
}

function renderSuggestions(items) {
  suggestions.textContent = "";
  lastSuggestions = items;
  if (!items.length) {
    suggestions.classList.remove("open");
    return;
  }
  items.slice(0, 7).forEach((item) => suggestions.append(card(item, true)));
  suggestions.classList.add("open");
}
function renderCards(items, title) {
  results.textContent = "";
  document.getElementById("resultsTitle").textContent = title;
  document.getElementById("resultCount").textContent =
    `${items.length} contenido${items.length === 1 ? "" : "s"} en esta página`;
  if (!items.length) {
    results.innerHTML =
      '<div class="empty">No encontramos contenidos para mostrar.</div>';
    return;
  }
  items.forEach((item) => results.append(card(item)));
}
function renderPagination(page, pages) {
  pagination.textContent = "";
  if (pages <= 1) return;
  const wanted = new Set(
    [1, pages, page - 2, page - 1, page, page + 1, page + 2].filter(
      (value) => value >= 1 && value <= pages,
    ),
  );
  let previous = 0;
  [...wanted]
    .sort((a, b) => a - b)
    .forEach((value) => {
      if (previous && value - previous > 1) {
        const dots = document.createElement("span");
        dots.textContent = "…";
        pagination.append(dots);
      }
      const button = document.createElement("button");
      button.textContent = value;
      button.classList.toggle("active", value === page);
      button.onclick = () => loadPage(value);
      pagination.append(button);
      previous = value;
    });
}
async function loadPage(page = 1) {
  searchMode = false;
  currentPage = page;
  controls.hidden = false;
  backHome.hidden = true;
  results.classList.add("loading");
  status.textContent = "Cargando contenidos recientes…";
  const response = await request({
    type: "GET_EXPLORE_PAGE",
    filter: currentFilter,
    page,
  });
  results.classList.remove("loading");
  if (!response?.ok) {
    status.textContent = response?.error || "No se pudo cargar el catálogo.";
    return;
  }
  currentPage = response.page;
  const title =
    currentFilter === "Película"
      ? "Películas recientes"
      : currentFilter === "Serie"
        ? "Series recientes"
        : "Últimos contenidos";
  renderCards(response.items, title);
  renderPagination(response.page, response.pages);
  status.textContent = `Catálogo actualizado · ${response.movieCount || 0} películas · ${response.seriesCount || 0} series`;
  scrollTo({ top: 0, behavior: "smooth" });
}

controls.querySelectorAll("[data-filter]").forEach(
  (button) =>
    (button.onclick = () => {
      currentFilter = button.dataset.filter;
      controls
        .querySelectorAll("button")
        .forEach((item) => item.classList.toggle("active", item === button));
      loadPage(1);
    }),
);

async function search(final = false) {
  const query = input.value.trim();
  if (query.length < 2) {
    renderSuggestions([]);
    return;
  }
  status.textContent = "Buscando coincidencias…";
  const response = await request({
    type: "SEARCH_EXPLORE_SITE",
    query,
    limit: final ? 36 : 8,
  });
  if (!response?.ok) {
    status.textContent = response?.error || "No se pudo completar la búsqueda.";
    return;
  }
  if (final) {
    searchMode = true;
    renderSuggestions([]);
    controls.hidden = true;
    pagination.textContent = "";
    backHome.hidden = false;
    renderCards(response.items, `Resultados para “${query}”`);
    document.getElementById("resultCount").textContent =
      `${response.items.length} resultado${response.items.length === 1 ? "" : "s"}`;
    status.textContent = "Resultados de búsqueda";
  } else {
    renderSuggestions(response.items);
    status.textContent = "Selecciona una coincidencia o pulsa Buscar";
  }
}
input.addEventListener("input", () => {
  clearTimeout(timer);
  timer = setTimeout(() => search(false), 260);
});
input.addEventListener("focus", () => {
  if (lastSuggestions.length && input.value.trim())
    renderSuggestions(lastSuggestions);
});
document.addEventListener("click", (event) => {
  if (!event.target.closest(".searchbox")) suggestions.classList.remove("open");
});
document.getElementById("searchForm").onsubmit = (event) => {
  event.preventDefault();
  search(true);
};
backHome.onclick = () => {
  input.value = "";
  renderSuggestions([]);
  loadPage(1);
};

function analysisHeader(catalog) {
  const head = document.createElement("div");
  head.className = "analysis-head";
  if (catalog.image) {
    const image = document.createElement("img");
    image.src = catalog.image;
    image.alt = "";
    head.append(image);
  } else {
    const blank = document.createElement("div");
    blank.className = "poster";
    fallbackPoster(blank);
    head.append(blank);
  }
  const copy = document.createElement("div"),
    kind = document.createElement("small"),
    title = document.createElement("h2"),
    description = document.createElement("p");
  kind.textContent = catalog.series
    ? "SERIE ENCONTRADA"
    : "PELÍCULA ENCONTRADA";
  title.textContent = catalog.title || "Contenido";
  description.textContent =
    catalog.description || "Pulsa reproducir para comenzar.";
  copy.append(kind, title, description);
  head.append(copy);
  return head;
}
function playSources(sources, meta, series = null) {
  chrome.runtime.sendMessage({
    type: "OPEN_SMART_PLAYER",
    urls: (sources || []).map((source) => source.url).filter(Boolean),
    title: meta.title,
    image: meta.image || "",
    postUrl: meta.postUrl || meta.url || "",
    series,
  });
}
function renderMovie(catalog) {
  analysis.textContent = "";
  analysis.append(analysisHeader(catalog));
  const tools = document.createElement("div");
  tools.className = "analysis-tools";
  tools.textContent = catalog.options?.length ? "Reproductor disponible" : "No disponible";
  analysis.append(tools);
  const list = document.createElement("div");
  list.className = "movie-options";
  if (!catalog.options?.length)
    list.innerHTML =
      '<div class="empty">No encontramos un reproductor disponible.</div>';
  else {
    const button = document.createElement("button");
    button.className = "single-play";
    button.innerHTML = '<img src="assets/hiroplay-icon.png" alt=""><span><b>Reproducir</b><small>HIRO PLAY elegirá automáticamente la mejor opción disponible</small></span><i>▶</i>';
    button.onclick = () => playSources(catalog.options, { title: catalog.title, image: catalog.image, postUrl: catalog.sourceUrl });
    list.append(button);
  }
  analysis.append(list);
}
function renderSeries(catalog) {
  analysis.textContent = "";
  analysis.append(analysisHeader(catalog));
  const episodes = catalog.series.episodes || [],
    seasons = [...new Set(episodes.map((item) => item.season ?? 1))],
    tools = document.createElement("div");
  tools.className = "analysis-tools";
  const count = document.createElement("span");
  count.textContent = `${seasons.length} temporada${seasons.length === 1 ? "" : "s"} · ${episodes.length} capítulo${episodes.length === 1 ? "" : "s"}`;
  tools.append(count);
  const list = document.createElement("div");
  list.className = "episodes";
  const showSeason = (season) => {
    list.querySelectorAll("[data-season]").forEach((item) => {
      item.hidden = Number(item.dataset.season) !== season;
      item.open = false;
    });
    const first = [...list.children].find((item) => !item.hidden);
    if (first) first.open = true;
  };
  if (seasons.length > 1) {
    const menu = document.createElement("details");
    menu.className = "season-menu";
    const summary = document.createElement("summary"),
      choices = document.createElement("div");
    summary.textContent = `Temporada ${seasons[0]}`;
    seasons.forEach((season, index) => {
      const button = document.createElement("button");
      button.textContent = `Temporada ${season}`;
      button.classList.toggle("active", index === 0);
      button.onclick = () => {
        showSeason(season);
        summary.textContent = `Temporada ${season}`;
        choices
          .querySelectorAll("button")
          .forEach((item) => item.classList.toggle("active", item === button));
        menu.open = false;
      };
      choices.append(button);
    });
    menu.append(summary, choices);
    tools.append(menu);
  }
  analysis.append(tools);
  episodes.forEach((episode, index) => {
    const details = document.createElement("details");
    details.className = "episode";
    details.dataset.season = episode.season ?? 1;
    const summary = document.createElement("summary"),
      number = document.createElement("span"),
      copy = document.createElement("span"),
      title = document.createElement("b"),
      meta = document.createElement("small"),
      arrow = document.createElement("span");
    number.textContent = episode.episode || index + 1;
    title.textContent =
      episode.label || `Capítulo ${episode.episode || index + 1}`;
    meta.textContent = episode.options?.length ? "Reproductor disponible" : "No disponible";
    arrow.textContent = "⌄";
    copy.append(title, meta);
    summary.append(number, copy, arrow);
    const providers = document.createElement("div");
    providers.className = "providers";
    if (!episode.options?.length)
      providers.innerHTML =
        "<small>No encontramos un reproductor disponible.</small>";
    else {
      const button = document.createElement("button");
      button.className = "episode-play";
      button.innerHTML = '<span><strong>Reproducir capítulo</strong><small>Selección automática</small></span><b><i>▶</i></b>';
      button.onclick = () => playSources(episode.options, { title: episode.label || catalog.title, image: episode.image || catalog.image, postUrl: episode.url }, { ...catalog.series, currentIndex: index });
      providers.append(button);
    }
    details.append(summary, providers);
    list.append(details);
  });
  analysis.append(list);
  showSeason(seasons[0]);
}
async function analyzeItem(item) {
  suggestions.classList.remove("open");
  modal.classList.add("open");
  analysis.innerHTML =
    '<div class="loading">Preparando el reproductor disponible…</div>';
  // En películas, usar primero las fuentes REALES guardadas durante la importación.
  // La URL de player.repelis24.life nunca se abre ni se usa como reproductor.
  const importedSources=(item.sources||[]).filter((url)=>{try{const h=new URL(url).hostname.toLowerCase();return h!=="player.repelis24.life"&&!h.endsWith(".player.repelis24.life");}catch{return false;}});
  if(item.type==="Película"&&importedSources.length){
    renderMovie({title:item.title||"Contenido",description:item.description||"",image:item.image||"",sourceUrl:item.url,options:importedSources.map((url)=>({url,provider:(()=>{try{return new URL(url).hostname;}catch{return "Fuente";}})(),kind:"provider"})),series:null});
    return;
  }
  const response = await request(
    { type: "ANALYZE_REMOTE_POST", site: SITE, url: item.url },
    60000,
  );
  if (!response?.ok) {
    analysis.innerHTML = `<div class="empty">${response?.error || "No se pudo analizar este resultado."}</div>`;
    return;
  }
  response.catalog.series
    ? renderSeries(response.catalog)
    : renderMovie(response.catalog);
}

request({ type: "GET_HIRO_AUTH_STATE", verify: true }).then((state) => {
  if (!state?.authenticated) {
    document.getElementById("authGate").hidden = false;
    document.querySelector("main").setAttribute("inert", "");
    return;
  }
  loadPage(1);
});
