import fse from 'fs-extra';
import path from 'path';
import { getLogger, LoggerOptions } from '@squiz/dx-logger-lib';

export interface InitPrompts {
  name: string;
  displayName: string;
  description: string;
  namespace: string;
}

const DEFAULT_PROMPTS: InitPrompts = {
  name: 'default',
  displayName: 'Default',
  description: 'Default component',
  namespace: 'default-namespace',
};

interface InitOptions {
  componentType: 'basic' | 'advanced';
  destination: string;
  loggingFormat?: LoggerOptions['format'];
  prompts?: Partial<InitPrompts>;
}

/**
 * componentInit initializes a new component
 * @param {object} options - The options object
 * @param {string} options.componentType - The type of component to initialize
 * @returns {void}
 */
export default async function componentInit(options: InitOptions) {
  const logger = getLogger({
    name: 'component-dev',
    format: options.loggingFormat || 'human',
    silent: process.env.NODE_ENV === 'test',
  });

  logger.info('Initializing component...');

  // Get our current script directory
  const currentScriptDir = path.resolve(__dirname);

  // Define the file source to move from
  const sourceFolder = path.join(currentScriptDir, 'templates', options.componentType);

  // Define the file destination to move to
  const destination = path.resolve(options.destination);

  // If the destination folder already exists, and it's not empty, throw an error
  if (await fse.pathExists(destination)) {
    const files = await fse.readdir(destination);
    if (files.length > 0) {
      throw new Error('The destination folder already exists and is not empty.');
    }
  } else {
    // If the destination folder doesn't exist, create it
    await fse.mkdirp(destination);
  }

  // Copy the contents of the source folder to the destination folder
  await fse.copy(sourceFolder, destination);
  await writeManifestVariables({ destination, prompts: Object.assign({}, DEFAULT_PROMPTS, options.prompts) });

  logger.info('Component initialized!');
}

async function writeManifestVariables(options: { destination: string; prompts: InitPrompts }) {
  const { destination, prompts } = options;

  const manifestPath = path.resolve(destination, 'manifest.json');

  const manifest = await fse.readJSON(manifestPath);

  manifest.name = prompts.name;
  manifest.displayName = prompts.displayName;
  manifest.description = prompts.description;
  manifest.namespace = prompts.namespace;

  await fse.writeJSON(manifestPath, manifest, { spaces: 2 });
}
