#!/usr/bin/env node

const fs = require('fs');
const readline = require('readline');
const path = require('path');
const Table = require('cli-table');
const { spawn } = require('child_process');
const yaml = require('js-yaml');

const args = process.argv.splice(process.execArgv.length + 2);
const userCommand = args[0];

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});


function initializePackage() {
  let isSocketRunning = null

  const configFilePath = path.join(__dirname, "init.json");

  try {
    const k = fs.statSync(configFilePath);
    isSocketRunning = true
  } catch (error) {
    isSocketRunning = false
    // console.error('isSocketRunning error', error)
  }

  if (isSocketRunning) {
    console.log("You have already initialized the onetab-cli npm package.");
    process.exit(1);
  } else {
    const nohupOutputFilePath = path.join(__dirname, "nohup.out");
    const child = spawn('node', [path.join(__dirname, 'client.js')], {
      detached: true,
      stdio: ['ignore', fs.openSync(`${__dirname}/nohup.out`, 'a'), fs.openSync(`${__dirname}/nohup.out`, 'a')],
    });
    
    child.unref();
    try {
      fs.writeFileSync(configFilePath, JSON.stringify({ initialized: true }, null, 2), "utf-8");
      console.log("The package is initialized successfully.");
      process.exit(1);          
    } catch (error) {
      console.error("Error initialization the package:", error);
      process.exit(1);
    }
  }
}

function saveConfiguredApplications(applications) {
  const configAppsFile = path.join(__dirname, "configuredApplications.json");
  const data = JSON.stringify(applications, null, 2);
  try {
    fs.writeFileSync(configAppsFile, data, "utf-8");
    console.log("File written successfully");
  } catch (error) {
    console.error("Error writing to the file:", error);
  }
}

function loadConfiguredApplications() {
  try {
    const data = fs.readFileSync(`${__dirname}/configuredApplications.json`, "utf-8");
    return JSON.parse(data) || [];
  } catch (error) {
    return [];
  }
}

async function start(appId) {
  console.log("Application ID:", appId);

  let configApps = loadConfiguredApplications();
  if (configApps?.length) {
    const app = configApps.filter((item) => item?.appId == appId);
    if (app?.length) {
      const lastIndexApp = app?.length === 1 ? app[0] : app[app?.length - 1]
      if (lastIndexApp?.status === 'active') {
        console.log(`The application with appId: ${appId} is already running...`);
        rl.close();
      } else {
        lastIndexApp.status = "active";
        saveConfiguredApplications(configApps);
        console.log(`The application with appId: ${appId} is started.`)
      }
    } else {
      console.log("No application found with the appId:", appId);
      rl.close();
    }
  } else {
    console.log("You haven't configured any application yet.");
    rl.close();
  }
}

async function stop(appId) {
  console.log("Application ID:", appId);

  let configApps = loadConfiguredApplications();
  if (configApps?.length) {
    const app = configApps.filter((item) => item.appId == appId);
    if (app?.length) {
      const lastIndexApp = app?.length === 1 ? app[0] : app[app?.length - 1]
      if (lastIndexApp?.status === 'stopped') {
        console.log(`The application with appId: ${appId} is already stopped.`);
        rl.close();
      } else {
        lastIndexApp.status = "stopped"; // Update application status to STOPPED
        saveConfiguredApplications(configApps);
        console.log(`The application with appId: ${appId} is stopped.`)
      }
    } else {
      console.log("No application found with the appId:", appId);
      rl.close();
    }
  } else {
    console.log("You haven't configured any application yet.");
    rl.close();
  }
}

function findYmlFiles(jsonPayload) {
  let configApps = loadConfiguredApplications();
  const currentDir = process.cwd();
  const ymlFiles = [];


  function traverseDir(currentDir) {
    let files = fs.readdirSync(currentDir);
    for (const file of files) {
      const filePath = path.join(currentDir, file);
      if (fs.statSync(filePath).isDirectory()) {
        if (path.basename(filePath) !== "node_modules") {
          traverseDir(filePath);
        }
      } else if (file.endsWith("onetab-pipeline.yml")) {
        ymlFiles.push(filePath);
      }
    }
  }

  traverseDir(currentDir);
  console.log("YML files:", ymlFiles);

  if (ymlFiles?.length) {
    const pushEventPayload = JSON.parse(jsonPayload)
    const branchPush = pushEventPayload?.ref.split('/').pop(); // Extracting branch name from the push event payload

    let lastIndexApp = null
   let filterConfigApps = null
    let configid =null
    if (configApps?.length) {
       filterConfigApps = configApps.filter(obj => obj?.appId == pushEventPayload?.repository?.id)
      if (filterConfigApps?.length) {
        lastIndexApp = filterConfigApps[filterConfigApps?.length - 1]
      }
    }

    const configAppsFile = path.join(__dirname, "configuredApplications.json");

    if (filterConfigApps?.length === 0 || configApps?.length === 0 || lastIndexApp?.status === 'active') {
      for (const ymlFile of ymlFiles) {
        const fileContent = fs.readFileSync(ymlFile, 'utf8');
        const workflowConfig = yaml.load(fileContent);
        const ymlBranch = workflowConfig.on.push.branches[0];
        const app = {
          uuid: null,
          appId: pushEventPayload?.repository?.id,
          appName: pushEventPayload?.repository?.full_name,
          commitId: pushEventPayload?.head_commit?.id,
          status: "active",
          path: ymlFile,
          pushEventPayload,
          branch:branchPush,
        };
          if (filterConfigApps?.length === 0||(configApps?.length === 0 || lastIndexApp?.status === 'active')){
            configApps.push(app);
            saveConfiguredApplications(configApps, configAppsFile);
        if (ymlBranch===branchPush){
           return ymlFiles;
        }
        else{
          console.log('Branch mismatch');
        }
      }
      else{
        console.log('condition not match');
      }
    }
  } else {
    console.log('Failed to locate onetab-pipeline yml file.');
  }
}
}


async function table() {
  console.log('__dirname ------------->', __dirname)
  const configApps = loadConfiguredApplications();
  if (configApps?.length) {
    const header = ["App ID", "App Name", "Status", "Path", "UUID"];
    const table = new Table({
      head: header,
    });

    const tableData = []
    configApps.forEach((app) => {
      const index = tableData.findIndex(obj => obj?.appId === app?.appId)
      if (index === -1) {
        table.push([app?.appId, app?.appName, app?.status, app?.path, app?.uuid]);
      } else {
        table.splice(index, 1, [app?.appId, app?.appName, app?.status, app?.path, app?.uuid]);
      }
      tableData.push({ appId: app?.appId, appName: app?.appName, status: app?.status, path: app?.path, uuid: app?.uuid })
    });
    console.log(table.toString());
    return table.toString();
  }
  console.log("No data to display.");
  return;
}

module.exports = {findYmlFiles};

switch (userCommand) {
  case "init":
    initializePackage();
    break;

  case "start":
    start(args[1]);
    process.exit(1);

  case "stop":
    stop(args[1]);
    process.exit(1);

  case "apps":
    table();
    process.exit(1);

  case "-help":
    console.info(`
      Usage: onetab-cli <command>
      Command List:
        1. onetab-cli init 
        2. onetab-cli start appId 
        3. onetab-cli stop appId 
        4. onetab-cli apps 
        5. onetab-cli -help 
      `
    );
    process.exit(1);

  default:
    console.log(`Run command "onetab-cli -help" to see the list of available commands.`);
}