import { headers } from "next/headers";
import { ApiError } from "@/lib/api-utils";

type BridgeMeta = {
  requestId: string;
  traceId: string;
  queryName: string;
};

type DocumentMetaResponse<T> = {
  doc: T;
  meta: BridgeMeta;
};

function getHeaderFirstValue(value: string | null): string {
  return String(value || "")
    .split(",")[0]
    .trim();
}

function parseHostParts(host: string): { hostname: string; port: string } {
  try {
    const parsed = new URL(`http://${host}`);
    return {
      hostname: parsed.hostname,
      port: parsed.port,
    };
  } catch {
    return {
      hostname: host,
      port: "",
    };
  }
}

function isLocalHostname(hostname: string): boolean {
  const normalized = hostname.replace(/^\[(.*)\]$/, "$1").trim().toLowerCase();
  return (
    normalized === "localhost" ||
    normalized === "127.0.0.1" ||
    normalized === "::1" ||
    normalized === "0.0.0.0" ||
    normalized === "::"
  );
}

function buildServerRequestOriginCandidates(headerList: Headers): string[] {
  const forwardedProto = getHeaderFirstValue(headerList.get("x-forwarded-proto"));
  const forwardedHost = getHeaderFirstValue(headerList.get("x-forwarded-host"));
  const host = forwardedHost || getHeaderFirstValue(headerList.get("host"));

  if (!host) {
    throw new Error("缺少 host 头，无法构造 bridge 请求地址");
  }

  const { hostname, port } = parseHostParts(host);
  const candidates = new Set<string>();
  const addCandidate = (proto: string, candidateHost: string) => {
    const normalizedProto = String(proto || "http").trim().toLowerCase() || "http";
    const normalizedHost = String(candidateHost || "").trim();
    if (!normalizedHost) return;
    candidates.add(`${normalizedProto}://${normalizedHost}`);
  };

  // 说明：优先保留浏览器实际请求的 origin，用于正常的同源自调用。
  addCandidate(forwardedProto || "http", host);

  // 说明：某些反代会把 x-forwarded-proto 设成 https，但本机 dev server 实际只监听 http。
  // 这里补一个 http 候选，避免 SSR 自请求被错误协议直接打挂。
  if ((forwardedProto || "").trim().toLowerCase() === "https") {
    addCandidate("http", host);
  }

  // 说明：localhost / 0.0.0.0 / ::1 这类本机地址在 Node 侧自调用时最容易踩解析差异，
  // 统一补 127.0.0.1 与 localhost 两个稳定候选，避免 fetch 因回环地址选择失败。
  if (isLocalHostname(hostname)) {
    const portSuffix = port ? `:${port}` : "";
    addCandidate("http", `127.0.0.1${portSuffix}`);
    addCandidate("http", `localhost${portSuffix}`);
  }

  return [...candidates];
}

function copyHeaderIfPresent(target: Headers, source: Headers, name: string) {
  const value = source.get(name);
  if (value) {
    target.set(name, value);
  }
}

async function fetchDocumentMetaResponse(url: URL, headersToSend: Headers): Promise<Response> {
  return await fetch(url, {
    method: "GET",
    headers: headersToSend,
    cache: "no-store",
  });
}

export async function fetchDocumentMetaViaBridge<T>(input: {
  documentId: string;
  workspaceId?: string | null;
}): Promise<DocumentMetaResponse<T> | null> {
  const headerList = await headers();
  const requestHeaders = new Headers();
  const originCandidates = buildServerRequestOriginCandidates(headerList);

  copyHeaderIfPresent(requestHeaders, headerList, "cookie");
  copyHeaderIfPresent(requestHeaders, headerList, "authorization");
  copyHeaderIfPresent(requestHeaders, headerList, "x-request-id");
  copyHeaderIfPresent(requestHeaders, headerList, "x-trace-id");
  copyHeaderIfPresent(requestHeaders, headerList, "x-session-id");
  copyHeaderIfPresent(requestHeaders, headerList, "x-source-channel");
  copyHeaderIfPresent(requestHeaders, headerList, "x-source-client");
  copyHeaderIfPresent(requestHeaders, headerList, "user-agent");

  let response: Response | null = null;
  let lastError: unknown = null;
  const errorMessages: string[] = [];

  for (const origin of originCandidates) {
    const url = new URL("/api/documents/meta", origin);
    url.searchParams.set("documentId", input.documentId);
    if (input.workspaceId?.trim()) {
      url.searchParams.set("workspaceId", input.workspaceId.trim());
    }

    try {
      response = await fetchDocumentMetaResponse(url, requestHeaders);
      break;
    } catch (error) {
      lastError = error;
      const message = error instanceof Error ? error.message : String(error);
      errorMessages.push(`${url.toString()} => ${message}`);
    }
  }

  if (!response) {
    const message =
      errorMessages.length > 0
        ? `bridge 自请求失败：${errorMessages.join(" | ")}`
        : "bridge 自请求失败：未生成可用的请求地址";
    throw new Error(message, { cause: lastError instanceof Error ? lastError : undefined });
  }

  if (response.status === 404) {
    return null;
  }

  if (!response.ok) {
    let message = "加载页面元信息失败";
    try {
      const payload = (await response.json()) as { error?: string };
      if (typeof payload?.error === "string" && payload.error.trim()) {
        message = payload.error;
      }
    } catch {
      // 说明：这里保留默认错误消息，避免 JSON 解析失败覆盖真实状态码。
    }
    throw new ApiError(message, response.status);
  }

  return (await response.json()) as DocumentMetaResponse<T>;
}
