// @ts-nocheck
import { assertReadOnlySql } from "../lib/sql-readonly.ts";
import { assertAllowedWriteSql } from "../lib/sql-write-allowlist.ts";
import { executeMariaDbWrite, isMariaDbConfigured, queryMariaDb } from "../db/mariadb-client.ts";

export function isEndpointConfigured(config) {
  return Boolean(
    config.endpoint.url &&
      (config.endpoint.token || (config.endpoint.loginUrl && config.endpoint.username && config.endpoint.password)),
  );
}

export async function queryEndpoint(config, sql) {
  assertReadOnlySql(sql);

  if (isMariaDbConfigured(config)) {
    return queryMariaDb(config, sql);
  }

  if (!isEndpointConfigured(config)) {
    return {
      configured: false,
      items: [],
      message: "Endpoint token is not configured in config/local.json.",
    };
  }

  let token = config.endpoint.token;
  let response = await sendQuery(config, sql, token);

  if (response.status === 401 && config.endpoint.username && config.endpoint.password) {
    token = await loginEndpoint(config);
    response = await sendQuery(config, sql, token);
  }

  const text = await response.text();
  let data;
  try {
    data = text ? JSON.parse(text) : {};
  } catch {
    data = { raw: text };
  }

  if (!response.ok) {
    const message = data?.message || data?.error || response.statusText;
    throw new Error(`Endpoint request failed (${response.status}): ${message}`);
  }

  return normalizeEndpointResponse(data);
}

export async function executeEndpointWrite(config, sql, { operation } = {}) {
  if (isMariaDbConfigured(config)) {
    return executeMariaDbWrite(config, sql);
  }

  assertAllowedWriteSql(sql, { operation });

  if (!isEndpointConfigured(config)) {
    return {
      configured: false,
      items: [],
      message: "Endpoint token is not configured in config/local.json.",
    };
  }

  let token = config.endpoint.token;
  let response = await sendQuery(config, sql, token);

  if (response.status === 401 && config.endpoint.username && config.endpoint.password) {
    token = await loginEndpoint(config);
    response = await sendQuery(config, sql, token);
  }

  const text = await response.text();
  let data;
  try {
    data = text ? JSON.parse(text) : {};
  } catch {
    data = { raw: text };
  }

  if (!response.ok) {
    const message = data?.message || data?.error || response.statusText;
    throw new Error(`Endpoint write failed (${response.status}): ${message}`);
  }

  return normalizeEndpointResponse(data);
}

async function sendQuery(config, sql, token) {
  const form = new FormData();
  form.append("query", sql);

  return fetch(config.endpoint.url, {
    method: "POST",
    headers: {
      Authorization: `Bearer ${token}`,
      Accept: "application/json",
    },
    body: form,
  });
}

async function loginEndpoint(config) {
  const form = new FormData();
  form.append("username", config.endpoint.username);
  form.append("password", config.endpoint.password);

  const response = await fetch(config.endpoint.loginUrl, {
    method: "POST",
    body: form,
  });
  const text = await response.text();
  let data;
  try {
    data = text ? JSON.parse(text) : {};
  } catch {
    data = { raw: text };
  }

  if (!response.ok) {
    const message = data?.message || data?.error || response.statusText;
    throw new Error(`Endpoint login failed (${response.status}): ${message}`);
  }

  const token = data?.token || data?.access_token || data?.data?.token || data?.data?.access_token;
  if (!token) {
    throw new Error("Endpoint login did not return a token.");
  }

  return token;
}

function normalizeEndpointResponse(data) {
  if (Array.isArray(data)) {
    return { configured: true, items: data };
  }

  if (Array.isArray(data.items)) {
    return { configured: true, items: data.items, meta: data };
  }

  if (Array.isArray(data.data)) {
    return { configured: true, items: data.data, meta: data };
  }

  if (Array.isArray(data.rows)) {
    return { configured: true, items: data.rows, meta: data };
  }

  return { configured: true, items: [], meta: data };
}
