import getCycleTLS from "./cycletls.js";
import v1_1Api from "./static/v1.1.js";

export default async function v1_1(queryName, { params, body, headers } = {}) {
  let entry = v1_1Api[queryName];
  if (!entry) {
    throw new Error(`v1.1 endpoint ${queryName} not found`);
  }

  const [method, baseUrl] = entry;

  let finalUrl = baseUrl;

  if (params && Object.keys(params).length) {
    const searchParams = new URLSearchParams(params);
    const separator = baseUrl.includes("?") ? "&" : "?";
    finalUrl = `${baseUrl}${separator}${searchParams.toString()}`;
  }

  const url = new URL(finalUrl);
  const pathname = url.pathname;

  const callerSetContentType = headers && Object.keys(headers).some(
    (k) => k.toLowerCase() === "content-type",
  );
  let finalBody = body;
  let coercedContentType = null;
  if (!callerSetContentType && typeof finalBody === "string" && finalBody.startsWith("{")) {
    try {
      const parsed = JSON.parse(finalBody);
      if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
        finalBody = new URLSearchParams(
          Object.fromEntries(
            Object.entries(parsed).map(([k, v]) => [k, v == null ? "" : String(v)]),
          ),
        ).toString();
        coercedContentType = "application/x-www-form-urlencoded";
      }
    } catch {}
  }

  const requestHeaders = {
    accept: "*/*",
    "accept-language": "en-US,en;q=0.9",
    authorization: `Bearer ${this.auth.client.bearer}`,
    "content-type": coercedContentType ?? "application/json",
    "x-csrf-token": this.auth.csrfToken,
    "x-twitter-active-user": "yes",
    "x-twitter-auth-type": "OAuth2Session",
    "x-twitter-client-language": "en",
    "x-client-transaction-id": await this.auth.generateTransactionId(
      method.toUpperCase(),
      pathname,
    ),
    priority: "u=1, i",
    "sec-ch-ua": '"Not(A:Brand";v="8", "Chromium";v="144"',
    "sec-ch-ua-mobile": "?0",
    "sec-ch-ua-platform": '"macOS"',
    "sec-fetch-dest": "empty",
    "sec-fetch-mode": "cors",
    "sec-fetch-site": "same-origin",
    "sec-gpc": "1",
    cookie:
      this.auth.client.headers.cookie + (this.elevatedCookies ? `; ${this.elevatedCookies}` : ""),
    ...headers,
  };

  const cycleTLS = await getCycleTLS();

  const res = await cycleTLS(
    finalUrl,
    {
      headers: requestHeaders,
      userAgent: this.auth.client.fingerprints.userAgent,
      ja3: this.auth.client.fingerprints.ja3,
      ja4r: this.auth.client.fingerprints.ja4r,
      body: finalBody || undefined,
      proxy: this.proxy || undefined,
      referrer: "https://x.com/",
    },
    method,
  );

  let bodyText;
  try {
    bodyText = await res.text();
  } catch {
    return res;
  }
  let bodyJson;
  if (bodyText) {
    try { bodyJson = JSON.parse(bodyText); } catch {}
  }
  if (bodyJson?.errors?.length) {
    const messages = bodyJson.errors
      .map((e) => e.message || (e.code != null ? `code ${e.code}` : "unknown"))
      .join("; ");
    throw new Error(`twitter v1.1 ${queryName} ${res.status}: ${messages}`);
  }
  return {
    status: res.status,
    headers: res.headers,
    json: async () => bodyJson,
    text: async () => bodyText,
  };
}
