import path from 'path';
import { tag as gitTag } from '@changesets/git';
import {
  fs,
  getPackageManager,
  getPnpmVersion,
  isMonorepo,
  semver,
} from '@modern-js/utils';
import { CHANGESET_PATH, execaWithStreamLog } from '../utils';

interface ReleaseOptions {
  tag: string;
  ignoreScripts: boolean;
  gitChecks: boolean;
  otp: string;
  provenance: boolean;
}

export async function release(options: ReleaseOptions) {
  const appDir = process.cwd();
  const packageManager = await getPackageManager(process.cwd());

  const params = ['publish'];

  const { tag, otp, ignoreScripts, gitChecks, provenance } = options;

  if (tag) {
    params.push('--tag');
    params.push(tag);
  }

  if (otp) {
    params.push('--otp');
    params.push(otp);
  }

  if (
    !isMonorepo(appDir) ||
    packageManager === 'yarn' ||
    packageManager === 'npm'
  ) {
    await execaWithStreamLog(process.execPath, [CHANGESET_PATH, ...params]);
    return;
  }

  params.push('-r');
  params.push('--filter');
  const pnpmVersion = await getPnpmVersion();
  if (pnpmVersion.startsWith('6')) {
    params.push('./packages/');
  } else {
    params.push('{./packages/**}');
  }
  params.push('--report-summary');

  if (ignoreScripts) {
    params.push('--ignore-scripts');
  }

  if (!gitChecks) {
    params.push('--no-git-checks');
  }

  if (provenance) {
    if (semver.lt(pnpmVersion, '8.4.0')) {
      console.warn(
        'current pnpm version not support --provenance, please upgrade pnpm version first.',
      );
    } else {
      params.push('--provenance');
    }
  }

  await execaWithStreamLog(packageManager, params);

  const pnpmPublishSummaryFile = path.join(appDir, 'pnpm-publish-summary.json');
  const publishInfo: {
    publishedPackages: Array<{ name: string; version: string }>;
  } = await fs.readJSON(pnpmPublishSummaryFile, 'utf-8');

  await Promise.all(
    (publishInfo.publishedPackages || []).map(pkg =>
      gitTag(`${pkg.name}@${pkg.version}`, appDir),
    ),
  );

  await fs.remove(pnpmPublishSummaryFile);
}
