// .storybook/main.ts
import {fileURLToPath} from 'node:url';
import {createRequire} from 'node:module';
import type {StorybookConfig} from '@storybook/react-webpack5';
import path, {dirname} from 'node:path';
import webpack from 'webpack';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const require = createRequire(import.meta.url);

const config: StorybookConfig = {
  stories: ['../src/**/*.mdx', '../src/**/*.stories.tsx'],

  addons: [
    '@storybook/addon-docs',
    '@storybook/addon-a11y',
    '@storybook/addon-webpack5-compiler-babel',
    '@chromatic-com/storybook',
    // NOTE: We handle CSS manually in webpackFinal to have full control
  ],

  babel: async (options: any) => ({
    ...options,
    sourceType: 'unambiguous',
    presets: [
      [
        '@babel/preset-env',
        {
          targets: [
            'last 2 Chrome versions',
            'last 2 Safari versions',
            'last 2 Firefox versions',
            'last 2 Edge versions',
            'last 3 iOS Major versions',
          ],
        },
      ],
      ['@babel/preset-react', {runtime: 'automatic', development: true}],
      '@babel/preset-typescript',
    ],
    plugins: ['macros', '@regrapes/babel-plugin-add-react-memo-displayname'],
  }),

  webpackFinal: async (cfg) => {
    const config: any = {...cfg};

    // ---------- Resolve / aliases ----------
    config.resolve ||= {};
    config.resolve.alias = {
      ...(config.resolve.alias ?? {}),
      src: path.resolve(__dirname, '../src'),
    };

    config.resolve.fallback = {
      ...(config.resolve.fallback ?? {}),
      process: require.resolve('process/browser'),
    };

    config.module ||= {};
    config.module.rules = config.module.rules || [];

    // ---------- CRITICAL: Remove Storybook's built-in CSS rules ----------
    // This prevents conflicts with our custom CSS Module configuration
    config.module.rules = config.module.rules.filter((rule: any) => {
      if (!rule) return true;
      if (!rule.test) return true;

      const testStr = rule.test.toString();
      // Remove any CSS-related rules (both .css and .scss/.sass)
      if (testStr.includes('css') || testStr.includes('scss') || testStr.includes('sass')) {
        return false;
      }
      return true;
    });

    // ---------- Add our CSS Module rules ----------
    // Rule 1: CSS Modules for *.module.css files
    config.module.rules.push({
      test: /\.module\.css$/,
      use: [
        require.resolve('style-loader'),
        {
          loader: require.resolve('css-loader'),
          options: {
            importLoaders: 1,
            modules: {
              // css-loader 7.x requires these options for `import css from` pattern
              namedExport: false,
              exportLocalsConvention: 'as-is',
              localIdentName: '[name]__[local]--[hash:base64:5]',
            },
          },
        },
        {
          loader: require.resolve('postcss-loader'),
          options: {
            implementation: require.resolve('postcss'),
          },
        },
      ],
    });

    // Rule 2: CSS Modules for styles/variables/*.css (design tokens with @value)
    config.module.rules.push({
      test: /\.css$/,
      include: [path.resolve(__dirname, '../src/styles/variables')],
      use: [
        require.resolve('style-loader'),
        {
          loader: require.resolve('css-loader'),
          options: {
            importLoaders: 1,
            modules: {
              namedExport: false,
              exportLocalsConvention: 'as-is',
              localIdentName: '[name]__[local]--[hash:base64:5]',
            },
          },
        },
        {
          loader: require.resolve('postcss-loader'),
          options: {
            implementation: require.resolve('postcss'),
          },
        },
      ],
    });

    // Rule 3: Regular CSS (non-modules) - must come AFTER module rules
    config.module.rules.push({
      test: /\.css$/,
      exclude: [
        /\.module\.css$/,
        path.resolve(__dirname, '../src/styles/variables'),
      ],
      use: [
        require.resolve('style-loader'),
        {
          loader: require.resolve('css-loader'),
          options: {
            importLoaders: 1,
            modules: false, // Plain CSS, not modules
          },
        },
        {
          loader: require.resolve('postcss-loader'),
          options: {
            implementation: require.resolve('postcss'),
          },
        },
      ],
    });

    // Rule 4: Sass/SCSS support
    config.module.rules.push({
      test: /\.s[ac]ss$/i,
      use: [
        require.resolve('style-loader'),
        {
          loader: require.resolve('css-loader'),
          options: {
            importLoaders: 2,
            modules: {
              auto: (resourcePath: string) =>
                resourcePath.endsWith('.module.scss') ||
                resourcePath.endsWith('.module.sass'),
              namedExport: false,
              exportLocalsConvention: 'as-is',
              localIdentName: '[name]__[local]--[hash:base64:5]',
            },
          },
        },
        {
          loader: require.resolve('sass-loader'),
          options: {
            implementation: require.resolve('sass'),
          },
        },
      ],
    });

    // ---------- Font rule tweak ----------
    config.module.rules = config.module.rules.map((rule: any) => {
      if (rule?.test && rule.test.toString().includes('woff')) {
        return {
          ...rule,
          test: /\.(svg|ico|jpg|jpeg|png|gif|webp|cur|ani|pdf)(\?.*)?$/,
        };
      }
      return rule;
    });

    // ---------- TS/TSX via babel-loader ----------
    config.module.rules.push({
      test: /\.(ts|tsx)$/,
      loader: require.resolve('babel-loader'),
      options: {
        presets: [['react-app', {flow: false, typescript: true}]],
        plugins: ['@regrapes/babel-plugin-add-react-memo-displayname'],
      },
    });

    // ---------- Plugins ----------
    config.plugins = [
      ...(config.plugins ?? []),
      new webpack.ProvidePlugin({
        process: 'process/browser',
      }),
      new webpack.DefinePlugin({
        'process.env.NODE_ENV': JSON.stringify(
          process.env.NODE_ENV ?? 'development',
        ),
      }),
    ];

    (config.resolve.extensions as string[]).push('.ts', '.tsx');

    return config;
  },

  staticDirs: ['public', '../design-tokens'],

  framework: {name: '@storybook/react-webpack5', options: {}},

  typescript: {reactDocgen: 'react-docgen-typescript'},
};

export default config;
