const elements = {
  url: document.getElementById("subscription-url"),
  importButton: document.getElementById("import-button"),
  refreshConfigButton: document.getElementById("refresh-config-button"),
  select: document.getElementById("profile-select"),
  subscriptionInfo: document.getElementById("subscription-info"),
  probeButton: document.getElementById("probe-button"),
  probeList: document.getElementById("probe-list"),
  probeUpdated: document.getElementById("probe-updated"),
  message: document.getElementById("message"),
  connectButton: document.getElementById("connect-button"),
  connectLabel: document.getElementById("connect-label"),
  statusPill: document.getElementById("status-pill")
};

const popupLifecycle = chrome.runtime.connect({ name: "popup-lifecycle" });
let currentState = null;
let busy = false;
let probing = false;

function request(message) {
  return new Promise((resolve, reject) => {
    chrome.runtime.sendMessage(message, (response) => {
      const runtimeError = chrome.runtime.lastError;
      if (runtimeError) return reject(new Error(runtimeError.message));
      if (!response?.ok) return reject(new Error(response?.error || "Неизвестная ошибка"));
      resolve(response.state);
    });
  });
}

function showMessage(text, ok = false) {
  elements.message.textContent = text;
  elements.message.classList.toggle("ok", ok);
  elements.message.hidden = !text;
}

function formatExpiry(status) {
  if (!status?.expires_at) return "";
  const date = new Date(status.expires_at);
  if (Number.isNaN(date.getTime())) return "";
  return `Подписка до ${new Intl.DateTimeFormat("ru-RU", { dateStyle: "medium" }).format(date)}`;
}

function formatUpdated(timestamp) {
  if (!timestamp) return "";
  const date = new Date(timestamp);
  if (Number.isNaN(date.getTime())) return "";
  return `Проверено ${new Intl.DateTimeFormat("ru-RU", {
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit"
  }).format(date)}`;
}

function formatProtocol(value) {
  const protocol = String(value || "").toLowerCase();
  if (protocol === "hysteria2") return "HYSTERIA 2";
  return protocol.toUpperCase();
}

function probePresentation(result) {
  if (probing) return { text: "Проверка…", className: "testing" };
  if (!result) return { text: "Не проверено", className: "" };
  if (Number.isFinite(result.latency_ms)) {
    const value = Number(result.latency_ms);
    const className = value < 150 ? "good" : value < 350 ? "medium" : "slow";
    return { text: `${value} мс`, className };
  }
  if (result.status === "offline") return { text: "Нет соединения", className: "offline" };
  if (result.check === "icmp") return { text: "Пинг закрыт", className: "" };
  return { text: "Не определено", className: "" };
}

function renderProbes(state) {
  const profiles = Array.isArray(state.profiles) ? state.profiles : [];
  const byTag = new Map(
    (Array.isArray(state.probeResults) ? state.probeResults : []).map((item) => [item.tag, item])
  );
  elements.probeList.replaceChildren();

  if (!profiles.length) {
    const empty = document.createElement("div");
    empty.className = "probe-empty";
    empty.textContent = "Загрузите подписку, чтобы проверить локации.";
    elements.probeList.append(empty);
  } else {
    for (const profile of profiles) {
      const result = byTag.get(profile.tag);
      const presentation = probePresentation(result);
      const row = document.createElement("div");
      row.className = "probe-row";
      row.classList.toggle("selected", profile.tag === state.selectedProfile);
      row.title = result?.detail || "Задержка до входного узла; это не тест скорости VPN.";

      const identity = document.createElement("div");
      const name = document.createElement("div");
      name.className = "probe-name";
      name.textContent = profile.tag;
      const protocol = document.createElement("span");
      protocol.className = "probe-protocol";
      protocol.textContent = formatProtocol(profile.protocol);
      identity.append(name, protocol);

      const value = document.createElement("div");
      value.className = `probe-value ${presentation.className}`.trim();
      value.textContent = presentation.text;
      row.append(identity, value);
      elements.probeList.append(row);
    }
  }

  const updated = probing ? "Проверка выполняется один раз…" : formatUpdated(state.probeUpdatedAt);
  elements.probeUpdated.textContent = updated;
  elements.probeUpdated.hidden = !updated;
}

function render(state) {
  currentState = state;
  const profiles = Array.isArray(state.profiles) ? state.profiles : [];

  if (document.activeElement !== elements.url) elements.url.value = state.subscriptionUrl || "";
  elements.select.replaceChildren();
  if (!profiles.length) {
    const option = document.createElement("option");
    option.value = "";
    option.textContent = "Сначала загрузите подписку";
    elements.select.append(option);
  } else {
    for (const profile of profiles) {
      const option = document.createElement("option");
      option.value = profile.tag;
      option.textContent = `${profile.tag} · ${formatProtocol(profile.protocol)}`;
      elements.select.append(option);
    }
    elements.select.value = state.selectedProfile || profiles[0].tag;
  }

  const expiry = formatExpiry(state.subscriptionStatus);
  elements.subscriptionInfo.textContent = expiry;
  elements.subscriptionInfo.hidden = !expiry;
  renderProbes(state);

  elements.statusPill.textContent = state.connected ? "Подключено" : "Отключено";
  elements.statusPill.classList.toggle("online", Boolean(state.connected));
  elements.connectLabel.textContent = state.connected ? "Отключить" : "Подключить";
  elements.connectButton.classList.toggle("connected", Boolean(state.connected));

  elements.url.disabled = busy || state.connected;
  elements.importButton.disabled = busy || state.connected;
  elements.refreshConfigButton.disabled = busy || state.connected || !state.subscriptionUrl;
  elements.select.disabled = busy || state.connected || !profiles.length;
  elements.probeButton.disabled = busy || probing || !profiles.length;
  elements.connectButton.disabled = busy || (!state.connected && !profiles.length);

  if (state.lastError) showMessage(state.lastError, false);
}

async function perform(action, successText = "") {
  busy = true;
  if (currentState) render(currentState);
  showMessage("");
  try {
    const state = await action();
    render(state);
    if (successText) showMessage(successText, true);
    return state;
  } catch (error) {
    showMessage(error.message || String(error), false);
    return null;
  } finally {
    busy = false;
    if (currentState) render({ ...currentState, lastError: "" });
  }
}

async function runProbe() {
  if (probing || !currentState?.profiles?.length) return;
  probing = true;
  render(currentState);
  try {
    const state = await request({ action: "probe_profiles" });
    render(state);
  } catch (error) {
    showMessage(`Не удалось проверить задержку: ${error.message || String(error)}`, false);
  } finally {
    probing = false;
    if (currentState) render(currentState);
  }
}

async function loadSubscription(successText) {
  const value = elements.url.value.trim() || currentState?.subscriptionUrl || "";
  if (!value) {
    showMessage("Вставьте ссылку подписки LunaTunnel.");
    return;
  }
  const state = await perform(
    () => request({ action: "import_subscription", subscriptionUrl: value }),
    successText
  );
  if (state) runProbe();
}

elements.importButton.addEventListener("click", () => {
  loadSubscription("Подписка загружена. Выберите локацию и подключитесь.");
});

elements.refreshConfigButton.addEventListener("click", () => {
  loadSubscription("Конфигурация и список локаций обновлены.");
});

elements.probeButton.addEventListener("click", runProbe);

elements.select.addEventListener("change", () => {
  const selectedProfile = elements.select.value;
  perform(() => request({ action: "select_profile", profile: selectedProfile }));
});

elements.connectButton.addEventListener("click", () => {
  if (currentState?.connected) {
    perform(() => request({ action: "disconnect" }), "LunaTunnel отключён.");
  } else {
    perform(() => request({ action: "connect" }), "Chrome подключён к LunaTunnel.");
  }
});

request({ action: "get_state" })
  .then((state) => {
    render(state);
    if (state.profiles?.length) runProbe();
  })
  .catch((error) => showMessage(error.message || String(error)));

window.addEventListener("unload", () => {
  try { popupLifecycle.disconnect(); } catch (_) {}
});
