/**
 * Step 2 — Testar conexao com o Fluig via Node.js (oauth-1.0a + https/http nativo)
 */

const { R, B, DIM, GREEN, AMBER, MUTED } = require("../colors");
const { stepHeader, ok, warn, erro, info, print } = require("../banner");

/**
 * Executa request HTTP com OAuth 1.0 para uma URL especifica.
 * Retorna { status, body } ou null em caso de erro de conexao.
 */
async function _doRequest(config, url) {
  try {
    const OAuth = require("oauth-1.0a");
    const crypto = require("crypto");

    const oauth = OAuth({
      consumer: {
        key: config.FLUIG_CONSUMER_KEY,
        secret: config.FLUIG_CONSUMER_SECRET,
      },
      signature_method: "HMAC-SHA1",
      hash_function(baseString, key) {
        return crypto.createHmac("sha1", key).update(baseString).digest("base64");
      },
    });

    const token = {
      key: config.FLUIG_ACCESS_TOKEN,
      secret: config.FLUIG_TOKEN_SECRET,
    };

    const requestData = { url, method: "GET" };
    const authHeader = oauth.toHeader(oauth.authorize(requestData, token));

    const parsedUrl = new URL(url);
    const httpModule = parsedUrl.protocol === "https:" ? require("https") : require("http");
    const verifySSL = config.FLUIG_VERIFY_SSL !== "false";

    return await new Promise((resolve) => {
      const req = httpModule.get(
        url,
        {
          headers: {
            ...authHeader,
            Accept: "application/json",
          },
          timeout: 15000,
          rejectUnauthorized: verifySSL,
        },
        (res) => {
          let body = "";
          res.on("data", (chunk) => (body += chunk));
          res.on("end", () => resolve({ status: res.statusCode, body }));
        }
      );
      req.on("error", (e) => {
        if (e.code === "ECONNREFUSED" || e.code === "ENOTFOUND") {
          erro(`Nao foi possivel conectar em: ${config.FLUIG_SERVER}`);
          warn("Verifique se a URL esta correta e o servidor acessivel");
        } else if (e.code === "UNABLE_TO_VERIFY_LEAF_SIGNATURE" || e.code === "CERT_HAS_EXPIRED" || e.code === "DEPTH_ZERO_SELF_SIGNED_CERT") {
          erro(`Erro SSL: ${e.code}`);
          warn("Desative a verificacao SSL na proxima pergunta ou use certificado valido");
        } else {
          erro(`Erro: ${e.message}`);
        }
        resolve(null);
      });
      req.on("timeout", () => {
        req.destroy();
        erro("Timeout — servidor demorou mais de 15s para responder");
        resolve(null);
      });
    });
  } catch (e) {
    erro(`Erro inesperado: ${e.message}`);
    return null;
  }
}

async function testConnection(config) {
  stepHeader(3, 5, "Testando conexao com o Fluig");

  // Credenciais vazias — pular
  if (!config.FLUIG_SERVER || !config.FLUIG_CONSUMER_KEY) {
    warn("Credenciais vazias — pulando teste de conexao");
    return false;
  }

  // Tenta com prefixo de modulo primeiro, depois sem
  const urls = [
    { url: `${config.FLUIG_SERVER}/dataset/api/v2/datasets?pageSize=1`, prefix: true },
    { url: `${config.FLUIG_SERVER}/api/v2/datasets?pageSize=1`, prefix: false },
  ];

  let resultado = null;
  let usaPrefix = true;

  for (const tentativa of urls) {
    info(`${MUTED}Tentando ${tentativa.url.substring(0, 65)}...${R}`);
    const res = await _doRequest(config, tentativa.url);
    if (res && res.status >= 200 && res.status < 500 && res.status !== 404) {
      resultado = res;
      usaPrefix = tentativa.prefix;
      break;
    }
    if (res && res.status === 404) {
      warn(`HTTP 404 — endpoint nao encontrado (tentando alternativa...)`);
      continue;
    }
    // Erro de conexao — nao adianta tentar outra URL
    if (!res) {
      resultado = null;
      break;
    }
    resultado = res;
  }

  // Salvar preferencia de prefixo no config para gravar no .env
  config.FLUIG_MODULE_PREFIX = usaPrefix ? "true" : "false";

  if (!resultado) {
    return false;
  }

  print("");

  if (resultado.status === 200) {
    ok(`Conexao estabelecida! ${GREEN}HTTP ${resultado.status}${R}`);
    if (!usaPrefix) {
      info(`${MUTED}Servidor sem prefixo de modulo (FLUIG_MODULE_PREFIX=false)${R}`);
    }
    try {
      const dados = JSON.parse(resultado.body);
      if (dados && typeof dados === "object" && "content" in dados) {
        ok("Datasets acessiveis no servidor");
      } else if (Array.isArray(dados)) {
        ok(`${dados.length} datasets encontrados`);
      }
    } catch (_) {}
    return true;
  } else if (resultado.status === 401) {
    erro("HTTP 401 — Credenciais invalidas ou expiradas");
    warn("Verifique Consumer Key/Secret e Access Token/Secret");
    return false;
  } else if (resultado.status === 403) {
    warn(`HTTP 403 — Conexao OK mas sem permissao neste endpoint`);
    return true;
  } else {
    warn(`HTTP ${resultado.status} — Resposta inesperada`);
    return false;
  }
}

module.exports = { testConnection };
