import path from 'path';
import { fileURLToPath } from 'url';
import HtmlWebpackPlugin from 'html-webpack-plugin';
import ReactRefreshWebpackPlugin from '@pmmmwh/react-refresh-webpack-plugin';
import MiniCssExtractPlugin from 'mini-css-extract-plugin';
import ESLintPlugin from 'eslint-webpack-plugin';
import { cpSync } from 'fs';
import { execSync } from 'child_process';
import webpack from 'webpack';
import fs from 'fs';
import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer';

// Get git commit hash
const getGitCommitHash = () => {
  try {
    return execSync('git rev-parse HEAD').toString().trim();
  } catch (e) {
    console.error('Failed to get git commit hash:', e);
    return 'unknown';
  }
};

const GIT_COMMIT_HASH = getGitCommitHash();

// Create a plugin to add the git commit hash directly to the HTML
class GitCommitPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('GitCommitPlugin', (compilation) => {
      HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync(
        'GitCommitPlugin',
        (data, cb) => {
          // Add a meta tag for the git commit hash
          const metaTag = `<meta name="git-commit" content="${GIT_COMMIT_HASH}">`;
          data.html = data.html.replace('</head>', `${metaTag}\n</head>`);
          cb(null, data);
        }
      );
    });
  }
}

// Plugin to generate currentHash.json file
class GitHashJsonPlugin {
  apply(compiler) {
    compiler.hooks.afterEmit.tap('GitHashJsonPlugin', (_compilation) => {
      const outputPath = path.join(compiler.options.output.path, 'currentHash.json');
      const content = JSON.stringify({
        gitCommit: GIT_COMMIT_HASH,
        buildTime: new Date().toISOString()
      }, null, 2);
      
      try {
        fs.mkdirSync(path.dirname(outputPath), { recursive: true });
        fs.writeFileSync(outputPath, content);
        console.log('Generated currentHash.json');
      } catch (err) {
        console.error('Error creating currentHash.json:', err);
      }
    });
  }
}

// Custom plugin to copy assets
const CopyAssetsPlugin = {
  apply: (compiler) => {
    compiler.hooks.afterEmit.tap('CopyAssetsPlugin', () => {
      // Copy assets directory but exclude fonts (webpack handles fonts with hashed names)
      const assetsSrc = path.resolve(__dirname, 'public/assets');
      const assetsDest = path.resolve(__dirname, 'dist/assets');
      try {
        // Copy all assets except fonts
        const items = fs.readdirSync(assetsSrc);
        for (const item of items) {
          if (item !== 'fonts') {
            const srcPath = path.join(assetsSrc, item);
            const destPath = path.join(assetsDest, item);
            cpSync(srcPath, destPath, { recursive: true });
          }
        }
        console.log('Assets copied successfully (fonts excluded - handled by webpack)');
      } catch (err) {
        console.error('Error copying assets:', err);
      }
      
      // Copy favicon.ico
      const faviconSrc = path.resolve(__dirname, 'public/favicon.ico');
      const faviconDest = path.resolve(__dirname, 'dist/favicon.ico');
      try {
        cpSync(faviconSrc, faviconDest);
        console.log('Favicon copied successfully');
      } catch (err) {
        console.error('Error copying favicon:', err);
      }

      // Copy index.html to payment/success file for callback
      const indexSrc = path.resolve(__dirname, 'dist/index.html');
      const paymentDir = path.resolve(__dirname, 'dist/payment');
      const paymentSuccessDest = path.resolve(__dirname, 'dist/payment/success');
      try {
        // Create payment directory if it doesn't exist
        if (!fs.existsSync(paymentDir)) {
          fs.mkdirSync(paymentDir, { recursive: true });
        }
        cpSync(indexSrc, paymentSuccessDest);
        console.log('Index.html copied to payment/success file successfully');
      } catch (err) {
        console.error('Error copying index.html to payment/success file:', err);
      }
    });
  },
};

// Custom plugin to inline CSS instead of loading externally
class InlineCssPlugin {
  apply(compiler) {
    compiler.hooks.compilation.tap('InlineCssPlugin', (compilation) => {
      HtmlWebpackPlugin.getHooks(compilation).beforeEmit.tapAsync(
        'InlineCssPlugin',
        (data, cb) => {
          // Only inline CSS in production mode
          if (isDevelopment) {
            cb(null, data);
            return;
          }

          // Find CSS assets and inline them
          let inlinedCss = '';
          const cssAssets = [];
          
          // Get CSS assets from compilation
          Object.keys(compilation.assets).forEach(assetName => {
            if (assetName.endsWith('.css')) {
              const cssContent = compilation.assets[assetName].source();
              inlinedCss += cssContent + '\n';
              cssAssets.push(assetName);
              
              // Remove CSS asset from compilation to prevent external file generation
              delete compilation.assets[assetName];
            }
          });

          if (inlinedCss.trim()) {
            // Remove existing CSS link tags from HTML
            data.html = data.html.replace(/<link[^>]*href="[^"]*\.css"[^>]*>/g, '');
            
            // JavaScript file preloading removed
            
            // Extract font URLs from CSS for preloading - DISABLED
            // const fontUrls = [];
            // const fontMatches = inlinedCss.match(/url\(([^)]+\.ttf)\)/g);
            // if (fontMatches) {
            //   fontMatches.forEach(match => {
            //     const fontUrl = match.replace(/url\(([^)]+)\)/, '$1').replace(/['"]/g, '');
            //     if (!fontUrls.includes(fontUrl)) {
            //       fontUrls.push(fontUrl);
            //     }
            //   });
            // }
            
            // Add font preload links - DISABLED
            let fontPreloads = '';
            // fontUrls.forEach(fontUrl => {
            //   fontPreloads += `<link rel="preload" href="${fontUrl}" as="font" crossorigin>\n`;
            // });
            
            // Add critical image preloads - DISABLED
            let imagePreloads = '';
            
            // Get the output filename to determine page type
            const outputPath = data.outputName || '';
            
            // Only preload on homepage - check if this is the main index.html
            const isHomePage = outputPath === 'index.html';
            
            // Define critical images array - only preload these on homepage
            // const criticalImages = [
            //   '/assets/images/filiale1.jpg',
            //   '/assets/images/filiale2.jpg',
            //   '/assets/images/seeds.jpg',
            //   '/assets/images/cutlings.jpg',
            //   '/assets/images/presse.jpg',
            //   '/assets/images/purpl.jpg'
            // ];
            
            // Only preload navigation images for homepage - DISABLED
            let preloadCount = 0;
            // if (isHomePage) {
            //   // Add the as="image" attribute to ensure proper preloading
            //   criticalImages.forEach(imagePath => {
            //     imagePreloads += `<link rel="preload" href="${imagePath}" as="image">\n`;
            //     preloadCount++;
            //   });
            // }
            
            // Add inlined CSS to head
            const styleTag = `<style type="text/css">${inlinedCss.trim()}</style>`;
            
            // Add only the style tag to head (no JS preloads)
            data.html = data.html.replace('</head>', `${styleTag}\n</head>`);
            
            console.log(`✅ Inlined CSS assets: ${cssAssets.join(', ')} (${Math.round(inlinedCss.length / 1024)}KB)`);
            // if (fontUrls.length > 0) {
            //   console.log(`✅ Added font preloads: ${fontUrls.length} fonts`);
            // }
            
            // Log whether images were preloaded
            console.log(`Page: ${outputPath} - Is homepage: ${isHomePage}`);
            
            // if (preloadCount > 0) {
            //   console.log(`✅ Added image preloads: ${preloadCount} critical images`);
            // } else {
            //   console.log(`✅ No image preloads added for ${outputPath}`);
            // }
          }
          
          cb(null, data);
        }
      );
    });
  }
}

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const isDevelopment = process.env.NODE_ENV !== 'production';
const isAnalyze = process.env.ANALYZE === 'true';
const proxyTarget = process.env.PROXY_TARGET || 'http://localhost:9303';

export default {
  mode: isDevelopment ? 'development' : 'production',
  entry: {
    main: './src/index.js'
  },
  target: 'web',
  output: {
    path: path.resolve(__dirname, 'dist'),
    filename: isDevelopment ? 'js/[name].[contenthash].bundle.js' : 'js/[name].[contenthash].js',
    chunkFilename: isDevelopment ? 'js/[name].[contenthash].chunk.js' : 'js/[name].[contenthash].chunk.js',
    clean: isDevelopment ? true : false,
    publicPath: '/'
  },
  devtool: isDevelopment ? 'source-map' : false,
  optimization: {
    runtimeChunk: 'single',
    moduleIds: 'deterministic',
    sideEffects: false,
    usedExports: true,
    minimize: !isDevelopment,
    minimizer: !isDevelopment ? [
      // Use default minimizers (terser-webpack-plugin for JS)
      '...',
    ] : [],
    splitChunks: {
      chunks: 'all',
      maxInitialRequests: 30,
      maxAsyncRequests: 30,
      minSize: 20000,
      cacheGroups: {
        // Split React and React DOM into separate chunk
        react: {
          test: /[\\/]node_modules[\\/](react|react-dom|react-router-dom)[\\/]/,
          name: 'react',
          priority: 30,
          reuseExistingChunk: true,
        },
        // Split commonly used MUI icons (used in main bundle and immediate-loading components)
        muiIconsCommon: {
          test: /[\\/]node_modules[\\/]@mui[\\/]icons-material[\\/].*(SmartToy|Palette|Search|Home|ShoppingCart|Close|ChevronLeft|ChevronRight|Person|Google|Add|Remove|Delete|KeyboardArrowUp|ZoomIn|Loupe|ExpandMore|ExpandLess|Mic|Stop|PhotoCamera|Menu|KeyboardReturn|ContentCopy|Cancel|CloudUpload|Star).*\.js$/,
          name: 'mui-icons-common',
          priority: 29,
          reuseExistingChunk: true,
          enforce: true,
        },
        // Split remaining MUI icons into separate chunk (for lazy-loaded components only)
        muiIcons: {
          test: /[\\/]node_modules[\\/]@mui[\\/]icons-material[\\/].*(Article|LockReset|AdminPanelSettings|Group|BarChart).*\.js$/,
          name: 'mui-icons', 
          priority: 28,
          reuseExistingChunk: true,
          chunks: 'async', // Only split icons used in lazy-loaded chunks
          enforce: true, // Ensure this rule is applied
        },
        // Split MUI core (styles + components)
        muiCore: {
          test: /[\\/]node_modules[\\/]@mui[\\/]/,
          name: 'mui-core',
          priority: 26,
          reuseExistingChunk: true,
        },
        // Split emotion (MUI's styling dependency)
        emotion: {
          test: /[\\/]node_modules[\\/]@emotion[\\/]/,
          name: 'emotion',
          priority: 24,
          reuseExistingChunk: true,
        },
        // Split chart.js into separate chunk (only loaded when needed)
        charts: {
          test: /[\\/]node_modules[\\/](chart\.js|react-chartjs-2)[\\/]/,
          name: 'charts',
          priority: 20,
          reuseExistingChunk: true,
        },
        // socket.io-client and its dependencies — always async, never initial
        socketio: {
          test: /[\\/]node_modules[\\/](socket\.io-client|engine\.io-client|@socket\.io|socket\.io-parser|socket\.io-msgpack-parser)[\\/]/,
          name: 'socketio',
          priority: 15,
          chunks: 'async',
          reuseExistingChunk: true,
        },
        // Other vendor libraries
        vendor: {
          test: /[\\/]node_modules[\\/]/,
          name: 'vendor',
          priority: 10,
          reuseExistingChunk: true,
        },
        // Common modules used across the app
        common: {
          name: 'common',
          minChunks: 2,
          priority: 5,
          reuseExistingChunk: true,
          enforce: true,
        },
      },
    },
  },
  module: {
    rules: [
      {
        test: /\.jsx?$/,
        exclude: /node_modules/,
        use: 'babel-loader',
      },
      {
        test: /\.css$/,
        use: [
          isDevelopment ? 'style-loader' : MiniCssExtractPlugin.loader,
          'css-loader'
        ],
      },
      {
        test: /\.(png|svg|jpg|jpeg|gif)$/i,
        type: 'asset/resource',
      },
      {
        test: /\.(woff|woff2|eot|ttf|otf)$/i,
        type: 'asset/resource',
      },
    ],
  },
  resolve: {
    extensions: ['.js', '.jsx'],
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './public/index.html',
      inject: true,
      scriptLoading: 'blocking',
    }),
    new GitCommitPlugin(),
    new GitHashJsonPlugin(),
    new webpack.DefinePlugin({
      'process.env.GIT_COMMIT_HASH': JSON.stringify(GIT_COMMIT_HASH)
    }),
    isDevelopment && new ReactRefreshWebpackPlugin({
      overlay: false, // Disable React Refresh overlay to prevent conflicts
    }),
    !isDevelopment && new MiniCssExtractPlugin({
      filename: 'css/[name].[contenthash].css',
      chunkFilename: 'css/[id].[contenthash].css',
    }),
    new ESLintPlugin({
      extensions: ['js', 'jsx'],
      emitWarning: true,
      emitError: true,
      failOnError: false,
      failOnWarning: false,
      quiet: false,
      eslintPath: 'eslint/use-at-your-own-risk'
    }),
    !isDevelopment && CopyAssetsPlugin,
    isAnalyze && new BundleAnalyzerPlugin({
      analyzerMode: 'static',
      reportFilename: 'bundle-report.html',
      openAnalyzer: true,
      generateStatsFile: true,
      statsFilename: 'bundle-stats.json',
    }),
    new InlineCssPlugin(),
  ].filter(Boolean),
  watchOptions: {
    // Only rebuild when file content actually changes, not just timestamps
    aggregateTimeout: 300, // Wait 300ms after a change before rebuilding
    poll: false, // Use native file watching instead of polling
    ignored: /node_modules/, // Ignore node_modules for performance
    followSymlinks: false, // Don't follow symlinks
  },
  devServer: {
    allowedHosts: 'all',
    compress: true,
    headers: {
      'Cache-Control': 'public, max-age=3600',
    },

    // Add proxy configuration for socket.io and API
    proxy: [
      {
        context: ['/socket.io'],
        target: proxyTarget,
        changeOrigin: true,
        ws: true,
        logLevel: 'debug',
        secure: proxyTarget.startsWith('https')
      },
      {
        context: ['/api'],
        target: proxyTarget,
        changeOrigin: true,
        logLevel: 'debug',
        secure: proxyTarget.startsWith('https')
      }
    ],

    hot: true,
    port: 9500,
    open: false,
    historyApiFallback: {
      index: '/index.html'
    },
    client: {
      logging: 'verbose',
      webSocketURL: 'wss://dev.seedheads.de/ws',
      overlay: {
        errors: true,
        warnings: true, // Disable warnings overlay to reduce noise
        runtimeErrors: true,
      },
    },
  },
};
