const path = require("path");
const fs = require("fs");
const axios = require("axios");
const https = require("https");
const { execSync } = require("child_process");

function shellQuote(value) {
  if (value === null || value === undefined || value === "") {
    return "''";
  }

  return `'${String(value).replace(/'/g, `'\\''`)}'`;
}

function maskCommand(command, secrets) {
  let safeCommand = command;

  for (const secret of secrets) {
    if (secret) {
      safeCommand = safeCommand.split(secret).join("****");
    }
  }

  return safeCommand;
}

async function runCodeAnalyzer(tl, options = {}) {
  const staticEngine = (options.staticEngine || "sonarqube").toLowerCase();
  const baseUrl = (options.baseUrl || "").replace(/\/$/, "");
  const cavissonToken = options.apiToken || "";

  if (staticEngine !== "sonarqube") {
    throw new Error(
      `Static engine '${staticEngine}' is selected, but currently only SonarQube logic is implemented.`
    );
  }

  if (!baseUrl) {
    throw new Error("Base URL is required for static scan.");
  }

  if (!cavissonToken || cavissonToken === "none") {
    throw new Error(
      "API Token is required in Cavisson Security Pipeline Service Connection when running static SonarQube scan."
    );
  }

  tl.setSecret(cavissonToken);

  const projectKey = tl.getInput("project", false) || "";
  const solution = tl.getInput("targetPath", false) || "";

  if (!projectKey.trim()) {
    throw new Error("Static Scan Project Key is required.");
  }

  console.log("========== Static Scan - Cavisson Code Analyzer ==========");
  console.log("Type        : static");
  console.log(`Engine      : ${staticEngine}`);
  console.log(`Base URL    : ${baseUrl}`);
  console.log(`Project Key : ${projectKey}`);
  console.log(`Target Path : ${solution || "Full Repo Scan"}`);
  console.log("=========================================================");

  const apiClient = axios.create({
    baseURL: `${baseUrl}/DashboardServer/v2/web/common/`,
    headers: {
      "Content-Type": "application/json",
      cavToken: cavissonToken
    },
    httpsAgent: new https.Agent({
      rejectUnauthorized: false
    })
  });

  const tokenRequest = {
    token: cavissonToken,
    validity_ms: 0,
    generated_time: 0
  };

  console.log(`Requesting tokens from: ${baseUrl}/DashboardServer/v2/web/common/getToken`);

  const tokenResponse = await apiClient.post("/getToken", tokenRequest);
  const responseData = tokenResponse.data;

  console.log(`Received token response: ${JSON.stringify(responseData)}`);

  if (!responseData.tokens) {
    throw new Error(`Failed to get token: ${JSON.stringify(responseData)}`);
  }

  const parsedData = JSON.parse(responseData.tokens);

  const sonarToken = parsedData.adminToken;
  const userToken = parsedData.userToken;
  const userName = parsedData.userName;

  if (!sonarToken || !userToken || !userName) {
    throw new Error("Invalid token response from Cavisson. adminToken/userToken/userName missing.");
  }

  tl.setSecret(sonarToken);
  tl.setSecret(userToken);

  let hostUrl = `${baseUrl}/cav-analysis`;
  hostUrl += `/userName/${userName}/cavToken/${cavissonToken}`;

  console.log("========== CAV Scanner Task ==========");
  console.log(`Project Key    : ${projectKey}`);
  console.log(`Host URL       : ${hostUrl.replace(cavissonToken, "****")}`);
  console.log(`Solution       : ${solution || "Full Repo Scan"}`);
  console.log(`Cavisson Token : ****`);
  console.log(`Sonar Token    : ****`);
  console.log(`User Token     : ****`);
  console.log(`User Name      : ${userName}`);
  console.log("======================================");

  const scriptPath = path.join(__dirname, "..", "cav_scanner.sh");

  if (!fs.existsSync(scriptPath)) {
    throw new Error(
      `cav_scanner.sh not found at ${scriptPath}. Copy cav_scanner.sh into cav-security-pipeline folder.`
    );
  }

  let command = [
    "bash",
    shellQuote(scriptPath),
    "--projectKey",
    shellQuote(projectKey),
    "--hostUrl",
    shellQuote(hostUrl),
    "--userToken",
    shellQuote(userToken),
    "--userName",
    shellQuote(userName),
    "--token",
    shellQuote(cavissonToken),
    "--isSonarCloud",
    shellQuote("false"),
    "--sonarToken",
    shellQuote(sonarToken)
  ].join(" ");

  if (solution) {
    command += ` --solution ${shellQuote(solution)}`;
  }

  console.log("Executing Cavisson Code Analyzer command:");
  console.log(maskCommand(command, [cavissonToken, sonarToken, userToken]));

  execSync(command, {
    stdio: "inherit",
    env: process.env,
    shell: true
  });

  console.log("Static SonarQube / Code Analyzer scan completed successfully.");
}

module.exports = {
  runCodeAnalyzer
};