import path from 'path';
import { existsSync, readFileSync } from 'fs';
import { isComponentName, checkComponentExportInIndex } from '../utils/index.js';

/**
 * Rule: component-structure/require-standard-files
 * Ensures component directories have required files (test, stories, etc.)
 */
export default {
  meta: {
    type: 'suggestion',
    docs: {
      description: 'Ensures component directories have the required files (test, stories, etc.)',
    },
    messages: {
      missingFiles:
        'Component {{ componentName }} is missing the required file: {{ requiredFile }}. Create this file to ensure proper component structure.',
      missingIndex: 'Component directory is missing an index.ts file. Create an index.ts file that exports the {{ componentName }} component.',
      missingExport: 'The {{ componentName }} component is not exported from the index.ts file. Add an export statement in the index.ts file.',
    },
  },
  create(context) {
    const filename = context.getFilename();

    // Only check .tsx component files
    if (!filename.endsWith('.tsx')) {
      return {};
    }

    // Skip test, story, and mdx files
    if (filename.includes('.test.') || filename.includes('.stories.') || filename.endsWith('.mdx')) {
      return {};
    }

    const pathParts = filename.split(/[\\/]/);
    const componentName = path.basename(filename, '.tsx');
    const folderPath = pathParts.slice(0, -1).join('/');

    // Skip files that are not components (e.g., utility files)
    if (!isComponentName(componentName)) {
      return {};
    }

    return {
      // Check for required files at the end of processing
      'Program:exit'(node) {
        // Required files for a component
        const requiredFiles = [`${componentName}.test.tsx`, `I${componentName}Props.ts`];

        // Check for each required file
        for (const requiredFile of requiredFiles) {
          const requiredPath = `${folderPath}/${requiredFile}`;
          if (!existsSync(requiredPath)) {
            context.report({
              node,
              messageId: 'missingFiles',
              data: {
                componentName,
                requiredFile,
              },
            });
          }
        }

        // Check for index.ts that exports the component
        const indexPath = `${folderPath}/index.ts`;
        if (!existsSync(indexPath)) {
          context.report({
            node,
            messageId: 'missingIndex',
            data: {
              componentName,
            },
          });
          return;
        }

        // Check if component is exported in index.ts
        try {
          const indexContent = readFileSync(indexPath, 'utf8');
          const isExported = checkComponentExportInIndex(indexContent, componentName);

          if (!isExported) {
            context.report({
              node,
              messageId: 'missingExport',
              data: {
                componentName,
              },
            });
          }
        } catch (error) {
          // when reading the index file fails, skip the check
          console.warn(error);
        }
      },
    };
  },
};
