/**
 * 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 * as tmp from 'tmp';
import { copyMetroConfig, createFileStructure } from './fsUtils';
import * as pathUtils from 'path';
import fs from 'node:fs';

let tmpDir = '';
let removeTmpDir = () => {};
let originalCwd = process.cwd();
let metroConfigPath = '';

beforeEach(async () => {
  const dir = tmp.dirSync();
  tmpDir = dir.name;
  removeTmpDir = dir.removeCallback;
  process.chdir(originalCwd);
});

afterEach(removeTmpDir);

function resolveRequest({
  originModulePath,
  moduleName,
  platform,
  rnProjectRootPath,
  nodeModulesPaths,
}: {
  originModulePath: string;
  moduleName: string;
  platform: string;
  nodeModulesPaths?: string[];
  rnProjectRootPath?: string;
}) {
  const rnProjectRootPath_ = rnProjectRootPath ?? tmpDir;
  metroConfigPath = copyMetroConfig(rnProjectRootPath_, 'metro.config.js');
  process.chdir(rnProjectRootPath_);
  const { createHarmonyMetroConfig } = require(metroConfigPath);
  const resolutionContext = {
    resolveRequest: (context: any, moduleName: string, platform: string) => {
      return { moduleName: moduleName, platform: platform };
    },
    originModulePath,
    nodeModulesPaths,
  };
  const resolveRequest_ = createHarmonyMetroConfig({
    reactNativeHarmonyPackageName: 'react-native-harmony',
  })?.resolver?.resolveRequest;
  return resolveRequest_(resolutionContext, moduleName, platform);
}

it('should redirect internal imports in harmony packages', async () => {
  createFileStructure(tmpDir, {
    node_modules: {
      'react-native-harmony-foo': {
        'package.json': `{
          "name": "react-native-harmony-foo",
          "harmony": {
            "alias": "react-native-foo",
            "redirectInternalImports": true
          }}`,
      },
    },
  });

  const resolution = resolveRequest({
    originModulePath: pathUtils.join(
      tmpDir,
      'node_modules',
      'react-native-foo',
      'src',
      'foo.ts'
    ),
    moduleName: './bar.ts',
    platform: 'harmony',
  });

  expect(resolution.moduleName).toEqual(
    pathUtils.posix.join('react-native-harmony-foo', 'src', 'bar.ts')
  );
});

it('should redirect internal imports in scoped harmony packages', async () => {
  createFileStructure(tmpDir, {
    node_modules: {
      '@rnoh': {
        'react-native-foo': {
          'package.json': `{
          "name": "@rnoh/react-native-harmony-foo",
          "harmony": {
            "alias": "react-native-foo",
            "redirectInternalImports": true
          }}`,
        },
      },
    },
  });

  const resolution = resolveRequest({
    originModulePath: pathUtils.join(
      tmpDir,
      'node_modules',
      'react-native-foo',
      'src',
      'foo.ts'
    ),
    moduleName: './bar.ts',
    platform: 'harmony',
  });

  expect(resolution.moduleName).toEqual(
    pathUtils.posix.join('@rnoh/react-native-foo', 'src', 'bar.ts')
  );
});

it('should redirect internal imports if alias is scoped', async () => {
  createFileStructure(tmpDir, {
    node_modules: {
      '@rnoh': {
        'react-native-harmony-foo': {
          'package.json': `{
          "name": "@rnoh/react-native-harmony-foo",
          "harmony": {
            "alias": "@org/react-native-foo",
            "redirectInternalImports": true
          }}`,
        },
      },
    },
  });

  const resolution = resolveRequest({
    originModulePath: pathUtils.join(
      tmpDir,
      'node_modules',
      '@org',
      'react-native-foo',
      'src',
      'foo.ts'
    ),
    moduleName: './bar.ts',
    platform: 'harmony',
  });

  expect(resolution.moduleName).toEqual(
    pathUtils.posix.join('@rnoh', 'react-native-harmony-foo', 'src', 'bar.ts')
  );
});

it('should not redirect internal imports when flag not set', async () => {
  createFileStructure(tmpDir, {
    node_modules: {
      'react-native-harmony-foo': {
        'package.json': `{
          "name": "react-native-harmony-foo",
          "harmony": {
            "alias": "react-native-foo"
          }}`,
      },
    },
  });

  const resolution = resolveRequest({
    originModulePath: pathUtils.join(
      tmpDir,
      'node_modules',
      'react-native-foo',
      'src',
      'foo.ts'
    ),
    moduleName: './bar.ts',
    platform: 'harmony',
  });

  expect(resolution.moduleName).toEqual('./bar.ts');
});

describe('monorepos', () => {
  it('should redirect import when project imports library', async () => {
    createFileStructure(tmpDir, {
      packages: {
        'my-project': {},
      },
      node_modules: {
        'react-native-harmony-foo': {
          'package.json': `{
            "name": "react-native-harmony-foo",
            "harmony": {
              "alias": "react-native-foo"
            }}`,
        },
      },
    });

    const resolution = resolveRequest({
      originModulePath: pathUtils.join(
        tmpDir,
        'packages',
        'my-project',
        'index.ts'
      ),
      moduleName: 'react-native-foo',
      platform: 'harmony',
      rnProjectRootPath: pathUtils.join(tmpDir, 'packages', 'my-project'),
      nodeModulesPaths: ['../../node_modules'],
    });

    expect(resolution.moduleName).toEqual('react-native-harmony-foo');
  });

  it('should redirect import when harmony library overrides internals of another library', async () => {
    createFileStructure(tmpDir, {
      packages: {
        'my-project': {},
      },
      node_modules: {
        'react-native-harmony-foo': {
          'package.json': `{
            "name": "react-native-harmony-foo",
            "harmony": {
              "alias": "react-native-foo",
              "redirectInternalImports": true
            }}`,
        },
      },
    });

    const resolution = resolveRequest({
      originModulePath: pathUtils.join(
        tmpDir,
        'node_modules',
        'react-native-foo',
        'src',
        'foo.ts'
      ),
      moduleName: './bar.ts',
      platform: 'harmony',
      rnProjectRootPath: pathUtils.join(tmpDir, 'packages', 'my-project'),
      nodeModulesPaths: ['../../node_modules'],
    });

    expect(resolution.moduleName).toEqual(
      pathUtils.posix.join('react-native-harmony-foo', 'src', 'bar.ts')
    );
  });
});