import "server-only";

const DEFAULT_MNOTE_WEB_INTERNAL_URL = "http://127.0.0.1:3104";
const DEFAULT_MNOTE_WEB_INTERNAL_URL_CANDIDATES = [
  DEFAULT_MNOTE_WEB_INTERNAL_URL,
  "http://localhost:3104",
];
const MNOTE_WEB_PROBE_PATH = "/health";
const RESOLVE_CACHE_TTL_MS = 30_000;

let cachedMnoteWebInternalUrl = "";
let cachedMnoteWebInternalUrlAt = 0;
let pendingMnoteWebInternalUrl: Promise<string> | null = null;

const normalizeMnoteWebInternalUrl = (raw?: string | null) => {
  const value = String(raw || "").trim().replace(/\/+$/, "");
  if (!value) return "";
  try {
    const url = new URL(value);
    if (url.protocol !== "http:" && url.protocol !== "https:") {
      return "";
    }
    return url.toString().replace(/\/+$/, "");
  } catch {
    return "";
  }
};

const getMnoteWebInternalUrlCandidates = () => {
  const candidates: string[] = [];
  const push = (value?: string | null) => {
    const normalized = normalizeMnoteWebInternalUrl(value);
    if (!normalized) return;
    if (!candidates.includes(normalized)) {
      candidates.push(normalized);
    }
  };

  push(process.env.MNOTE_WEB_INTERNAL_URL);

  for (const raw of String(process.env.MNOTE_WEB_INTERNAL_URL_CANDIDATES || "").split(",")) {
    push(raw);
  }

  for (const candidate of DEFAULT_MNOTE_WEB_INTERNAL_URL_CANDIDATES) {
    push(candidate);
  }

  return candidates.length > 0 ? candidates : [DEFAULT_MNOTE_WEB_INTERNAL_URL];
};

const probeMnoteWebInternalUrl = async (candidate: string) => {
  try {
    const url = new URL(MNOTE_WEB_PROBE_PATH, `${candidate}/`);
    const response = await fetch(url, {
      method: "GET",
      redirect: "follow",
      cache: "no-store",
      signal: AbortSignal.timeout(2_500),
    });
    return response.ok;
  } catch {
    return false;
  }
};

export const resolveMnoteWebInternalUrl = async () => {
  const now = Date.now();
  if (cachedMnoteWebInternalUrl && now - cachedMnoteWebInternalUrlAt < RESOLVE_CACHE_TTL_MS) {
    return cachedMnoteWebInternalUrl;
  }

  if (pendingMnoteWebInternalUrl) {
    return pendingMnoteWebInternalUrl;
  }

  pendingMnoteWebInternalUrl = (async () => {
    const candidates = getMnoteWebInternalUrlCandidates();
    for (const candidate of candidates) {
      if (await probeMnoteWebInternalUrl(candidate)) {
        return candidate;
      }
    }
    return candidates[0] || DEFAULT_MNOTE_WEB_INTERNAL_URL;
  })();

  try {
    const resolved = await pendingMnoteWebInternalUrl;
    cachedMnoteWebInternalUrl = resolved;
    cachedMnoteWebInternalUrlAt = Date.now();
    return resolved;
  } finally {
    pendingMnoteWebInternalUrl = null;
  }
};
