/**
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

import { HvigorNode, hvigor } from "@ohos/hvigor";
import {
  OhosAppContext,
  OhosPluginId,
  OhosHapContext,
  Target,
} from "@ohos/hvigor-ohos-plugin";
import * as pathUtils from "node:path";
import { CommandExecutor } from "../../common/CommandExecutor";
import { BundlerConfig as BaseBundlerConfig, Subtask } from "../../types";
import { Logger } from "../../common/Logger";

export type BundlerConfig = Omit<
  BaseBundlerConfig,
  "dev" | "hermescOptions"
> & {
  dev: string;
  hermescOptions: string;
};

export class BundlerSubtask implements Subtask {
  constructor(
    private commandExecutor: CommandExecutor,
    private logger: Logger,
    private node: HvigorNode,
    private input: {
      nodeModulesPath: string;
      bundler: BundlerConfig;
    }
  ) {}

  run(): void {
    hvigor.nodesEvaluated(() => {
      const appContext: OhosAppContext = this.node.getContext(
        OhosPluginId.OHOS_APP_PLUGIN
      );
      const buildMode = appContext.getBuildMode();
      this.node.subNodes((node: HvigorNode) => {
        const hapContext: OhosHapContext = node.getContext(
          OhosPluginId.OHOS_HAP_PLUGIN
        );
        hapContext?.targets((target: Target) => {
          const targetName = target.getTargetName();
          node.registerTask({
            name: `${targetName}@CreateJSBundle`,
            run: () => {
              const bundlerOptions = this.input.bundler;
              if (
                !this.input.nodeModulesPath ||
                !bundlerOptions.enabled ||
                buildMode !== "release"
              ) {
                this.logger.warn(`[bundler] skipped`);
                return;
              }
              delete bundlerOptions.enabled;
              const projectRootPath = pathUtils.resolve(this.input.nodeModulesPath, '..');
              const configRelativeToRoot = bundlerOptions.config ?
                pathUtils.relative(projectRootPath, bundlerOptions.config) : undefined;
              const bundleOutputeRelativeToRoot = bundlerOptions.bundleOutput ?
                pathUtils.relative(projectRootPath, bundlerOptions.bundleOutput) : undefined;
              const assetsDestRelativeToRoot = bundlerOptions.assetsDest ?
                pathUtils.relative(projectRootPath, bundlerOptions.assetsDest) : undefined;
              const sourcemapOutputRelativeToRoot = bundlerOptions.sourcemapOutput ?
                pathUtils.relative(projectRootPath, bundlerOptions.sourcemapOutput) : undefined;
              try {
                this.commandExecutor.run(
                  `node_modules${pathUtils.sep}.bin${pathUtils.sep}react-native bundle-harmony`,
                  {
                    ...bundlerOptions,
                    config: configRelativeToRoot,
                    bundleOutput: bundleOutputeRelativeToRoot,
                    assetsDest: assetsDestRelativeToRoot,
                    sourcemapOutput: sourcemapOutputRelativeToRoot
                  },
                  {
                    encoding: "utf-8",
                    stdio: "ignore",
                    cwd: projectRootPath,
                  }
                );
                this.logger.info(`[bundler] done generating bundle`);
              } catch (err) {
                this.logger.error(`[bundler] failed: ${err}`);
              }
            },
            dependencies: [`${targetName}@ProcessResource`],
            postDependencies: [`${targetName}@CompileResource`],
          });
        });
      });
    });
  }
}