/* ************************************************************************** */
/*                              PREBUILD SCRIPT                               */
/*                                                                            */
/* This script performs the following operations:                             */
/*   1. Processes action metadata template file                               */
/*   2. Parses action metadata from the processed file                        */
/*   3. Creates TypeScript definition for the action metadata                 */
/*   4. Generates a dynamic module loader                                     */
/*   5. Saves the generated TypeScript definition and module loader           */
/* ************************************************************************** */

import { parseActionMetadataFromFile, processActionMetadataTemplateFile, createTypeScriptDefinitionForActionMetadata, createModuleLoaderTypeScriptDefinitionForActionMetadata } from "@/utils/actions/action-metadata";
import { SPLIT_BY_WORDS_AND_GROUP_ACTION_PARAMETER_PATH_PARSER } from "@/utils/actions/action-parameter-path-parser";
import { WINDOWS_NEWLINE } from "@/utils/environment";
import { FileNotFoundError } from "@/utils/errors";
import { TypeScriptDocument } from "@/utils/typescript";
import { basename } from "node:path";

/**
 * Path to the action metadata template file.
 */
const ACTION_METADATA_TEMPLATE_FILE = "./action.template.yml";

/**
 * Path to the processed action metadata file.
 */
const ACTION_METADATA_FILE = "./action.yml";

/**
 * Path to the output TypeScript definition file for action metadata.
 */
const ACTION_METADATA_TYPESCRIPT_DEFINITION_FILE = "./src/action.ts";

/**
 * Path to the output dynamic module loader TypeScript file.
 */
const DYNAMIC_MODULE_LOADER_FILE = "./src/utils/reflection/module-loader.g.ts";

/**
 * Processing options.
 */
const OPTIONS: PrebuildOptions = {
    // The name of the source file everything else is generated from.
    sourceFileName: basename(ACTION_METADATA_TEMPLATE_FILE),

    // The encoding used for reading and writing files.
    encoding: "utf8",

    // Disable ESLint in the generated TypeScript files.
    disableESLint: true,

    // Add a warning message about auto-generated files
    generateAutoGeneratedWarningMessage: true,

    // Remove fields that are only used in the template from the generated files.
    removeTemplateOnlyFields: true,

    // // The root path for module imports.
    rootPath: "@/",

    // The path parser used for action parameter paths.
    pathParser: SPLIT_BY_WORDS_AND_GROUP_ACTION_PARAMETER_PATH_PARSER,

    // The newline character(s) to use in the generated files.
    newline: WINDOWS_NEWLINE,

    // The number of spaces for indentation in the generated files.
    tabSize: 4,

    // The maximum line width for the generated files.
    lineWidth: 80,
};

/**
 * Processing options' type.
 */
type PrebuildOptions = Exclude<
    & Parameters<typeof processActionMetadataTemplateFile>[2]
    & Parameters<typeof parseActionMetadataFromFile>[1]
    & Parameters<typeof createTypeScriptDefinitionForActionMetadata>[1]
    & Parameters<typeof createModuleLoaderTypeScriptDefinitionForActionMetadata>[1]
    & Parameters<TypeScriptDocument["save"]>[1]
, string>;

// Ensure the action metadata template file exists
FileNotFoundError.throwIfNotFound(ACTION_METADATA_TEMPLATE_FILE);

// Process the action metadata template file
await processActionMetadataTemplateFile(ACTION_METADATA_TEMPLATE_FILE, ACTION_METADATA_FILE, OPTIONS);

// Parse the action metadata from the processed file
const metadata = await parseActionMetadataFromFile(ACTION_METADATA_FILE, OPTIONS);

// Create the TypeScript definition for the action metadata
const metadataTypeScriptDefinition = createTypeScriptDefinitionForActionMetadata(metadata, OPTIONS);
await metadataTypeScriptDefinition.save(ACTION_METADATA_TYPESCRIPT_DEFINITION_FILE, OPTIONS);

// Generate the dynamic module loader
const moduleLoaderTypeScriptDefinition = createModuleLoaderTypeScriptDefinitionForActionMetadata(metadata, OPTIONS);
await moduleLoaderTypeScriptDefinition.save(DYNAMIC_MODULE_LOADER_FILE, OPTIONS);