import { dirname } from 'node:path';

import {
  getFilesInDirectory,
  isComponentYmlFile,
} from '../utils/components.js';

import type { Rule as EslintRule } from 'eslint';

const REQUIRED_FILES = ['component.yml', 'index.jsx'];
const ALLOWED_FILES = ['component.yml', 'index.jsx', 'index.css'];
const IGNORED_FILES = [
  'dist', // 'dist' dir is automatically generated by the canvas build command.
];

function isFileAllowed(fileName: string, allowedFiles: string[]): boolean {
  return allowedFiles.some((allowedFile) => allowedFile === fileName);
}

const rule: EslintRule.RuleModule = {
  meta: {
    type: 'problem',
    docs: {
      description:
        'Validates that component directory contains only allowed files',
    },
  },
  create(context: EslintRule.RuleContext): EslintRule.RuleListener {
    if (!isComponentYmlFile(context)) {
      return {};
    }

    return {
      Program: function (node) {
        const componentDir = dirname(context.filename);
        const filesInDirectory = getFilesInDirectory(componentDir).filter(
          (file) => !IGNORED_FILES.includes(file),
        );

        REQUIRED_FILES.filter(
          (file) => !filesInDirectory.includes(file),
        ).forEach((file) => {
          context.report({
            node,
            message: `Missing required component file: ${file}.`,
          });
        });

        const disallowedFiles = filesInDirectory.filter(
          (file) => !isFileAllowed(file, ALLOWED_FILES),
        );

        if (disallowedFiles.length > 0) {
          context.report({
            node,
            message:
              `Component directory contains disallowed files: ${disallowedFiles.join(', ')}. ` +
              `Only the following files are allowed: ${ALLOWED_FILES.join(', ')}. ` +
              `Other files will be overwritten by the "canvas download" command.`,
          });
        }
      },
    };
  },
};

export default rule;
