const transformer = (file, api, options) => {
  const j = api.jscodeshift;
  const root = j(file.source);
  
  // Get the selected components from options
  const selectedComponentsString = options.selectedComponents;
  const selectedComponents = selectedComponentsString 
    ? selectedComponentsString.split(',').map(c => c.trim()).filter(c => c)
    : [];
  
  // Early return if no components selected
  if (selectedComponents.length === 0) {
    return file.source;
  }

  // Collect all components to migrate from fictoan-react
  const allMigratedComponents = new Set();

  // First, collect existing @setu/components imports
  const existingSetuComponents = new Set();
  root
    .find(j.ImportDeclaration)
    .filter(path => path.node.source.value === '@setu/components')
    .forEach(path => {
      const specifiers = path.node.specifiers || [];
      specifiers.forEach(spec => {
        if (
          spec.type === 'ImportSpecifier' &&
          spec.imported.type === 'Identifier'
        ) {
          existingSetuComponents.add(spec.imported.name);
        }
      });
    });

  // Find all import declarations from 'fictoan-react' or "fictoan-react"
  root
    .find(j.ImportDeclaration)
    .filter(path => path.node.source.value === 'fictoan-react')
    .forEach(path => {
      const specifiers = path.node.specifiers;

      const migratedSpecifiers =
        specifiers?.filter(
          specifier =>
            specifier.type === 'ImportSpecifier' &&
            specifier.imported.type === 'Identifier' &&
            selectedComponents.includes(specifier.imported.name)
        ) || [];

      // Add migrated components to the set
      migratedSpecifiers.forEach(spec => {
        allMigratedComponents.add(spec.imported.name);
      });

      const migratedNames = migratedSpecifiers.map(spec => spec.imported.name);
      const remainingSpecifiers =
        specifiers?.filter(
          specifier =>
            specifier.type === 'ImportSpecifier' &&
            specifier.imported.type === 'Identifier' &&
            !migratedNames.includes(specifier.imported.name)
        ) || [];

      if (remainingSpecifiers.length) {
        // update the original import statement with the remaining specifiers.
        path.node.specifiers = remainingSpecifiers;
      } else {
        // original import statement is now empty, remove it completely.
        j(path).remove();
      }
    });

  // Merge existing @setu/components with newly migrated components
  const allSetuComponents = new Set([
    ...existingSetuComponents,
    ...allMigratedComponents,
  ]);

  // Remove any existing @setu/components imports to avoid duplicates
  root
    .find(j.ImportDeclaration)
    .filter(path => path.node.source.value === '@setu/components')
    .remove();

  // Create a single consolidated import for @setu/components if we have any components
  if (allSetuComponents.size > 0) {
    const consolidatedSpecifiers = Array.from(allSetuComponents)
      .sort() // Sort for consistent ordering
      .map(componentName =>
        j.importSpecifier(
          j.identifier(componentName),
          j.identifier(componentName)
        )
      );

    const consolidatedImport = j.importDeclaration(
      consolidatedSpecifiers,
      j.literal('@setu/components')
    );

    // Insert the consolidated import at the top of the file
    const allImports = root.find(j.ImportDeclaration);
    if (allImports.length > 0) {
      // Insert after the last remaining import
      allImports.at(-1).insertAfter(consolidatedImport);
    } else {
      // If no imports exist, add at the beginning of the file
      const program = root.find(j.Program);
      if (program.length > 0) {
        program.get('body').unshift(consolidatedImport);
      }
    }
  }

  return root.toSource();
};

module.exports = transformer;
module.exports.default = transformer;