import { createRunOncePlugin, withDangerousMod } from '@expo/config-plugins';
import { ExpoConfig } from '@expo/config-types';
// @ts-expect-error missing types
import withDevLauncher from 'expo-dev-launcher/app.plugin';
// @ts-expect-error missing types
import withDevMenu from 'expo-dev-menu/app.plugin';
import fs from 'fs';
import path from 'path';

const pkg = require('expo-dev-client/package.json');

const REACT_NATIVE_CONFIG_JS = `// File created by expo-dev-client/app.plugin.js

module.exports = {
  dependencies: {
    ...require('expo-dev-client/dependencies'),
  },
};
`;

function withReactNativeConfigJs(config: ExpoConfig) {
  return withDangerousMod(config, [
    'ios',
    async config => {
      const filename = path.join(config.modRequest.projectRoot, 'react-native.config.js');
      try {
        const config = fs.readFileSync(filename, 'utf8');
        if (!config.includes('expo-dev-client/dependencies')) {
          throw new Error(
            `Could not add expo-dev-client dependencies to existing file ${filename}. See expo-dev-client installation instructions to add them manually.`
          );
        }
      } catch (error) {
        if (error.code === 'ENOENT') {
          // The file doesn't exist, so we create it.
          fs.writeFileSync(filename, REACT_NATIVE_CONFIG_JS);
        } else {
          throw error;
        }
      }
      return config;
    },
  ]);
}

function withDevClient(config: ExpoConfig) {
  config = withDevMenu(config);
  config = withDevLauncher(config);
  config = withReactNativeConfigJs(config);
  return config;
}

export default createRunOncePlugin(withDevClient, pkg.name, pkg.version);
