import path from 'path';
import clear from 'clear';

// Import helpers
import showChooser from '../helpers/showChooser';
import getDeploymentConfig from '../operations/getDeploymentConfig';
import print from '../helpers/print';
import exec from '../helpers/exec';
import getPackageJSON from '../helpers/getPackageJSON';
import validateNodeVersion from '../helpers/validateNodeVersion';
import deployCustomNow from './deployCustomNow';
import config from '../helpers/config';

// Import shared types
import Deployment from '../types/Deployment';

// Import constants
import APP_DIRECTORY from '../constants/APP_DIRECTORY';

/**
 * Perform a deploy now
 * @author Gabe Abrams
 * @param deployment the currently selected deployment
 */
const deployNow = async (deployment: Deployment) => {
  // Check for custom deployment process
  let doingCustomDeployment = false;
  if (deployment.customStackInfo && config.customStackDeploymentProcess) {
    // Ask the user if they want to do the custom deployment process
    const { tag } = showChooser({
      title: 'Multiple Deployment Processes',
      question: 'Which deployment process do you want to run?',
      options: [
        {
          description: 'App (Main Deployment Process)',
          tag: 'A',
        },
        {
          description: `Custom (${config.customStackDeploymentProcess.description})`,
          tag: 'C',
        },
      ],
    });
    doingCustomDeployment = (tag === 'C');
  }
  if (doingCustomDeployment) {
    // Run custom deployment process
    await deployCustomNow(deployment);
    return;
  }

  // Normal app deployment process

  // Choose an operation
  const { tag } = showChooser({
    question: 'Have you changed the deploy config?',
    options: [
      {
        description: 'Yes, I changed env vars, branch, and/or version',
        tag: 'Y',
      },
      {
        description: 'No, I just want to deploy with same config',
        tag: 'N',
      },
    ],
    title: 'Ready to Deploy',
  });

  // Show loading indicator
  clear();
  console.log('Loading current info...\n');
  const deployConfig = getDeploymentConfig(deployment);

  // Get last part of the app image
  const parts = deployConfig.appImage.split(':');
  const branchOrVersion = parts[parts.length - 1];

  // Check type
  const isVersion = branchOrVersion.includes('.');

  // Process branch name
  const processedBranchName = branchOrVersion.replace('-', '/');

  // Information
  clear();
  print.title('About to Deploy');
  console.log('');
  console.log('Information:');
  console.log(`Deploying to: ${deployment.name}`);
  console.log(`Branch: ${isVersion ? 'main branch' : processedBranchName}`);
  console.log(`Version: ${isVersion ? branchOrVersion : '[Most Recent Build]'}`);
  if (tag === 'Y') {
    console.log('Operation: update deploy config then restart');
  } else {
    console.log('Operation: restart with unmodified config');
  }
  console.log('');

  // Ask for confirmation
  const confirmOption = showChooser({
    question: 'Ready to continue?',
    options: [
      {
        description: 'Yes',
        tag: 'Y',
      },
      {
        description: 'No',
        tag: 'N',
      },
    ],
    dontClear: true,
  });
  if (confirmOption.tag === 'N') {
    // Cancel
    clear();
    print.title('Cancelled!');
    console.log('');
    print.enterToContinue();
    return;
  }

  // Validate Node version
  await validateNodeVersion();

  // Ask user if they waited for the action to build
  const packageJSON = getPackageJSON(path.join(APP_DIRECTORY, 'package.json'));
  if (packageJSON.repository && packageJSON.repository.url) {
    const actionsPanelURL = (
      packageJSON.repository.url
        .replace('git+http', 'http')
        .replace('.git', '/actions')
    );
    
    // Print warning
    clear();
    print.title('Did you wait for the action to finish?');
    console.log('');
    console.log('Actions panel:');
    console.log(actionsPanelURL);
    console.log('');
    print.enterToContinue();
  }

  // Redeploy
  if (tag === 'Y') {
    clear();
    console.log('Loading diff...\n');

    // Confirm diff
    const diff = exec(`./node_modules/.bin/caccl-deploy stack --profile ${deployment.profile} --app ${deployment.app} diff`);
    console.log('');
    print.title('Confirm Deploy Config Diff:');
    console.log('');
    console.log(diff);

    // Ask user to confirm
    const secondaryConfirmOption = showChooser({
      question: 'Ready to continue?',
      options: [
        {
          description: 'Yes',
          tag: 'Y',
        },
        {
          description: 'No',
          tag: 'N',
        },
      ],
      dontClear: true,
    });
    if (secondaryConfirmOption.tag === 'N') {
      // Cancel
      clear();
      print.title('Cancelled!');
      console.log('');
      print.enterToContinue();
      return;
    }

    // Deploy (update config)
    exec(
      `./node_modules/.bin/caccl-deploy stack --profile ${deployment.profile} --app ${deployment.app} deploy -y`,
      true,
    );
  } else {
    // Restart
    clear();
    console.log('Restarting service...');
    console.log('');
    exec(
      `./node_modules/.bin/caccl-deploy restart --profile ${deployment.profile} --app ${deployment.app} -y`,
      true,
    );
  }

  // Confirmation
  clear();
  print.title('Deploy Successful');
  console.log('');
  print.enterToContinue();
};

export default deployNow;
