import path from 'path';
import fs, { mkdirSync } from 'fs';
import micromatch from 'micromatch';
import { isDefined } from '../types';
function tryToLoadTestsData(filename) {
  try {
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    return require(filename);
  } catch (_) {
    /* noop */
  }
}
const actualRegex = /^(.*)-actual-(\d+)\.png$/i;
function approve(dirents, srcPath, dstPath, testPaths, isMatch) {
  dirents.filter(dirent => dirent.isFile()).map(dirent => actualRegex.exec(dirent.name)).filter(isDefined).filter(([fileName, imageName]) => !testPaths || testPaths.find(([token]) => token == imageName) && isMatch(path.join(srcPath, fileName))).reduce((images, [, imageName, retry]) => Number(retry) > (images.get(imageName) ?? -1) ? images.set(imageName, Number(retry)) : images, new Map()).forEach((retry, imageName) => {
    mkdirSync(dstPath, {
      recursive: true
    });
    fs.copyFileSync(path.join(srcPath, `${imageName}-actual-${retry}.png`), path.join(dstPath, `${imageName}.png`));
  });
}
function traverse(srcPath, dstPath, testPaths, isMatch) {
  const dirents = fs.readdirSync(srcPath, {
    withFileTypes: true
  });
  approve(dirents, srcPath, dstPath, testPaths, isMatch);
  dirents.filter(dirent => dirent.isDirectory()).map(dirent => [dirent.name, testPaths === null || testPaths === void 0 ? void 0 : testPaths.map(([token, ...restPath]) => token == dirent.name ? restPath : null).filter(isDefined)]).filter(([, paths]) => !paths || paths.length > 0).forEach(([dirname, paths]) => traverse(path.join(srcPath, dirname), path.join(dstPath, dirname), paths, isMatch));
}
export default function update(config, grepPattern) {
  const {
    reportDir,
    screenDir
  } = config;
  const isMatch = grepPattern ? micromatch.matcher(grepPattern, {
    contains: true
  }) : () => true;
  const testsMeta = tryToLoadTestsData(`${reportDir}/tests.json`);
  const testsReport = tryToLoadTestsData(`${reportDir}/data`);
  let testPaths = null;
  if (testsMeta && testsReport) {
    testPaths = Object.values(testsMeta).filter(isDefined).filter(({
      id
    }) => {
      var _testsReport$id;
      return ((_testsReport$id = testsReport[id]) === null || _testsReport$id === void 0 ? void 0 : _testsReport$id.status) == 'failed';
    }).map(({
      storyPath,
      testName,
      browser
    }) => [...storyPath, ...(testName ? [testName] : []), browser]);
  }
  traverse(reportDir, screenDir, testPaths, value => isMatch(path.relative(reportDir, value)));
}