import {
  convertNxGenerator,
  ensurePackage,
  formatFiles,
  GeneratorCallback,
  readProjectConfiguration,
  Tree,
  updateProjectConfiguration,
} from '@nrwl/devkit';
import { nxVersion } from '../../utils/versions';

import storiesGenerator from '../stories/stories';
import { addResolverMainFieldsToMetroConfig } from './lib/add-resolver-main-fields-to-metro-config';
import { createStorybookFiles } from './lib/create-storybook-files';
import { replaceAppImportWithStorybookToggle } from './lib/replace-app-import-with-storybook-toggle';

import { StorybookConfigureSchema } from './schema';

async function generateStories(host: Tree, schema: StorybookConfigureSchema) {
  await storiesGenerator(host, {
    project: schema.name,
    ignorePaths: schema.ignorePaths,
  });
}

export async function storybookConfigurationGenerator(
  host: Tree,
  schema: StorybookConfigureSchema
): Promise<GeneratorCallback> {
  await ensurePackage(host, '@nrwl/storybook', nxVersion);
  const { configurationGenerator } = await import('@nrwl/storybook');

  const installTask = await configurationGenerator(host, {
    name: schema.name,
    uiFramework: '@storybook/react-native',
    configureCypress: false,
    js: false,
    linter: schema.linter,
    standaloneConfig: schema.standaloneConfig,
    tsConfiguration: schema.tsConfiguration,
  });

  addStorybookTask(host, schema.name);
  createStorybookFiles(host, schema);
  replaceAppImportWithStorybookToggle(host, schema);
  addResolverMainFieldsToMetroConfig(host, schema);

  if (schema.generateStories) {
    await generateStories(host, schema);
  }

  await formatFiles(host);
  return installTask;
}

function addStorybookTask(host: Tree, projectName: string) {
  const projectConfig = readProjectConfiguration(host, projectName);
  projectConfig.targets['storybook'] = {
    executor: '@nrwl/react-native:storybook',
    options: {
      searchDir: [projectConfig.root],
      outputFile: './.storybook/story-loader.js',
      pattern: '**/*.stories.@(js|jsx|ts|tsx|md)',
      silent: false,
    },
  };

  updateProjectConfiguration(host, projectName, projectConfig);
}

export default storybookConfigurationGenerator;
export const storybookConfigurationSchematic = convertNxGenerator(
  storybookConfigurationGenerator
);
