import { execSync } from 'child_process';
import { existsSync, readdirSync } from 'fs';
import { join } from 'path';
import * as fse from 'fs-extra';
import * as axios from 'axios';
import { getVersions } from 'ice-npm-utils';

// Set by github actions
const branchName = process.env.BRANCH_NAME;
const rootDir = join(__dirname, '../');
const REGISTRY = 'https://registry.npmjs.org/';

// 依赖关系影响发布顺序
const orderedPackages = [
  'ice-npm-utils',
  '@ice/pkg',
  '@ice/pkg-plugin-component',
  '@ice/pkg-plugin-docusaurus',
];

if (!branchName) {
  throw new Error('Only support publish in GitHub Actions env');
}

(async () => {
  const packageDirs = getPackagesPaths(join(rootDir, 'packages'));
  const packages = packageDirs.map((pkgDir) => {
    const pkgData = fse.readJSONSync(join(pkgDir, 'package.json'));
    return { pkgDir, pkgData };
  }).sort((a, b) => {
    const aIndex = orderedPackages.indexOf(a.pkgData.name);
    const bIndex = orderedPackages.indexOf(b.pkgData.name);
    return aIndex - bIndex;
  });

  for (const pkgInfo of packages) {
    // eslint-disable-next-line no-await-in-loop
    await publishPackage(pkgInfo);
  }
})().catch((err) => {
  console.error(err);
  process.exit(1);
});

async function publishPackage({ pkgDir, pkgData }) {
  const { version, name } = pkgData;
  const npmTag = branchName === 'master' ? 'latest' : 'beta';

  const versionExist = await checkVersionExist(name, version, REGISTRY);
  if (versionExist) {
    console.log(`${name}@${version} 已存在,无需发布。`);
    return;
  }

  const isProdVersion = /^\d+\.\d+\.\d+$/.test(version);
  if (branchName === 'master' && !isProdVersion) {
    throw new Error(`禁止在 master 分支发布非正式版本 ${version}`);
  }

  if (branchName !== 'master' && isProdVersion) {
    console.log(`非 master 分支 ${branchName},不发布正式版本 ${version}`);
    return;
  }

  console.log('start publish', version, npmTag);
  execSync('npm install', {
    cwd: pkgDir,
    stdio: 'inherit',
  });
  execSync(`npm publish --tag ${npmTag}`, {
    cwd: pkgDir,
    stdio: 'inherit',
  });

  console.log('start notify');
  const response = await axios.default({
    url: process.env.DING_WEBHOOK,
    method: 'post',
    headers: {
      'Content-Type': 'application/json;charset=utf-8',
    },
    data: {
      msgtype: 'markdown',
      markdown: {
        title: `${name}@${version} 发布成功`,
        text: `${name}@${version} 发布成功`,
      },
    },
  });
  console.log('notify success', response.data);
}

async function checkVersionExist(
  name: string,
  version: string,
  registry?: string,
): Promise<boolean> {
  try {
    const versions = await getVersions(name, registry);
    return versions.indexOf(version) !== -1;
  } catch (err) {
    console.error('checkVersionExist error', err);
    return false;
  }
}

function getPackagesPaths(dir) {
  const packagesPaths: string[] = readdirSync(dir).map((dirname) => {
    return join(dir, dirname);
  }).filter((dirpath) => {
    return existsSync(join(dirpath, 'package.json'));
  });

  return packagesPaths;
}