import * as logSymbols from 'log-symbols';

import { CliEnhancer, CLI_USAGE_ERROR } from '@alwaysai/alwayscli';
import { audit, openAuditLog } from './util';
import { ALWAYSAI_AUDIT_LOG } from './environment';
import { postTrackingDataToSegment } from './infrastructure/post-tracking-data-to-segment';

// NOTE: THis doesn't cover model ID's since those don't have a leading argument flag
const SENSITIVE_KEYWORDS = [
  '--email',
  '--password',
  '--project',
  '--deviceId',
  '--model',
  '--releaseHash',
  '--name',
  '--tag'
];

export function cleanArgv(argv: string[]) {
  const clean: string[] = [];
  let cleaning = false;
  for (const arg of argv) {
    if (cleaning) {
      // Push cleaned values until next argument
      if (!arg.includes('--')) {
        clean.push('******');
        continue;
      }
    }
    cleaning = false;
    if (SENSITIVE_KEYWORDS.includes(arg)) {
      clean.push(arg);
      cleaning = true;
    } else {
      clean.push(arg);
    }
  }
  return clean;
}

export const enhancer: CliEnhancer =
  (argvInterface) =>
  async (...argv: string[]) => {
    if (ALWAYSAI_AUDIT_LOG) {
      try {
        await openAuditLog(ALWAYSAI_AUDIT_LOG);
      } catch (exception) {
        console.error(
          `${logSymbols.warning} Failed to open audit log: "${exception.message}"`
        );
      }
    }
    const argvString = cleanArgv(argv).join(' ');
    audit(`start "${argvString}"`);
    const trackingPromise = postTrackingDataToSegment(argvString);
    try {
      const returnValue = await argvInterface(...argv);

      await new Promise<void>((resolve) => {
        audit(`end "${returnValue}"`, () => {
          resolve();
        });
      });
      await trackingPromise;
      return returnValue;
    } catch (exception) {
      if (exception.code !== CLI_USAGE_ERROR) {
        await Promise.all([
          postTrackingDataToSegment(argvString, exception),
          trackingPromise
        ]);
      } else {
        await trackingPromise;
      }
      throw exception;
    }
  };
