/**
 * 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 fs from 'node:fs';
import pathUtils from 'node:path';
import { execSync } from 'child_process';
import { unlinkSync } from 'fs';

const REPO_ROOT_PATH = pathUtils.resolve(__dirname, '..');
const RNOH_PKG_ROOT_PATH = pathUtils.join(
  REPO_ROOT_PATH,
  'packages',
  'react-native-harmony'
);

const REACT_NATIVE_SUBMODULE_PATH = pathUtils.join(
  REPO_ROOT_PATH,
  'packages',
  'react-native'
);

const REACT_NATIVE_PATCH_PATH = pathUtils.join(
  REPO_ROOT_PATH,
  'packages',
  'react-native.patch'
);

const REACT_NATIVE_PKG_ROOT_PATH = pathUtils.join(
  REACT_NATIVE_SUBMODULE_PATH,
  'packages',
  'react-native'
);

const REACT_COMMON_SRC_PATH = pathUtils.join(
  REACT_NATIVE_PKG_ROOT_PATH,
  'ReactCommon'
);

const REACT_COMMON_DEST_PATH = pathUtils.join(
  REPO_ROOT_PATH,
  'packages',
  'tester',
  'harmony',
  'react_native_openharmony',
  'src',
  'main',
  'cpp',
  'third-party',
  'rn',
  'ReactCommon'
);

try {
  applyPatch();
  syncJS('delegates');
  syncJS('Libraries');
  syncJS('src');
  syncJS('types');
  syncCpp();
} finally {
  cleanReactNativeSubmodule();
}

function applyPatch() {
  cleanReactNativeSubmodule();
  execSync(`git apply --whitespace=fix ${REACT_NATIVE_PATCH_PATH}`, {
    cwd: REACT_NATIVE_SUBMODULE_PATH,
  });
}

function cleanReactNativeSubmodule() {
  execSync('git reset --hard HEAD && git clean -dfx', {
    cwd: REACT_NATIVE_SUBMODULE_PATH,
  });
}

function syncJS(pathRelativeToRNRoot: string) {
  const destPath = pathUtils.join(RNOH_PKG_ROOT_PATH, pathRelativeToRNRoot);
  if (!fs.existsSync(destPath)) {
    fs.mkdirSync(destPath);
  }
  removeUntrackedFiles(destPath);
  fs.cpSync(
    pathUtils.join(REACT_NATIVE_PKG_ROOT_PATH, pathRelativeToRNRoot),
    destPath,
    { recursive: true }
  );
  console.log(`synchronized: ${pathUtils.relative(process.cwd(), destPath)}`);
}

function removeUntrackedFiles(dirPath: string): void {
  const stdout = execSync('git ls-files --others', {
    cwd: dirPath,
    encoding: 'utf-8',
  });
  const files = stdout.split('\n').filter((file) => file);

  files.forEach((file) => {
    const fullPath = pathUtils.resolve(dirPath, file);
    unlinkSync(fullPath);
  });
}

function syncCpp() {
  if (!fs.existsSync(REACT_COMMON_DEST_PATH)) {
    fs.mkdirSync(REACT_COMMON_DEST_PATH);
  }
  removeUntrackedFiles(REACT_COMMON_DEST_PATH);
  fs.cpSync(REACT_COMMON_SRC_PATH, REACT_COMMON_DEST_PATH, { recursive: true });
  console.log(
    `synchronized: ${pathUtils.relative(process.cwd(), REACT_COMMON_DEST_PATH)}`
  );
}