/**
 * @fileoverview CSS Framework Integration Command for OrdoJS CLI
 * Handles integration of CSS frameworks like Tailwind CSS
 */

import { Command } from 'commander';
import { promises as fs } from 'fs';
import path from 'path';
import { OrdoJSCSSFrameworkIntegration, type CSSFramework } from '../../core/src/compiler/css-framework-integration.js';
import { CLIError, ErrorType } from '../utils/error.js';
import { logger } from '../utils/logger.js';

/**
 * Register CSS framework integration command
 */
export function registerCSSFrameworkCommand(program: Command): void {
  const cssFrameworkCommand = program
    .command('css-framework')
    .description('Integrate CSS frameworks with OrdoJS')
    .option('-f, --framework <framework>', 'CSS framework to integrate (tailwind, bootstrap, bulma, foundation, custom)', 'tailwind')
    .option('-o, --output <dir>', 'Output directory for generated files', './')
    .option('--no-purge', 'Disable CSS purging (keep all unused classes)')
    .option('--content <paths>', 'Content paths for purging (comma-separated)', './src/**/*.ordo')
    .option('--custom-css <path>', 'Custom CSS file path (for custom framework)')
    .option('--no-minify', 'Disable CSS minification')
    .option('--source-maps', 'Generate source maps')
    .option('--postcss-plugins <plugins>', 'Additional PostCSS plugins (comma-separated)')
    .action(async (options) => {
      await cssFrameworkCommand(options);
    });

  // Add subcommands for specific frameworks
  cssFrameworkCommand
    .command('tailwind')
    .description('Integrate Tailwind CSS')
    .option('-o, --output <dir>', 'Output directory', './')
    .option('--no-purge', 'Disable CSS purging')
    .option('--content <paths>', 'Content paths for purging', './src/**/*.ordo')
    .option('--no-minify', 'Disable CSS minification')
    .option('--source-maps', 'Generate source maps')
    .action(async (options) => {
      await integrateTailwind(options);
    });

  cssFrameworkCommand
    .command('bootstrap')
    .description('Integrate Bootstrap CSS')
    .option('-o, --output <dir>', 'Output directory', './')
    .option('--no-minify', 'Disable CSS minification')
    .option('--source-maps', 'Generate source maps')
    .action(async (options) => {
      await integrateBootstrap(options);
    });

  cssFrameworkCommand
    .command('bulma')
    .description('Integrate Bulma CSS')
    .option('-o, --output <dir>', 'Output directory', './')
    .option('--no-minify', 'Disable CSS minification')
    .option('--source-maps', 'Generate source maps')
    .action(async (options) => {
      await integrateBulma(options);
    });

  cssFrameworkCommand
    .command('foundation')
    .description('Integrate Foundation CSS')
    .option('-o, --output <dir>', 'Output directory', './')
    .option('--no-minify', 'Disable CSS minification')
    .option('--source-maps', 'Generate source maps')
    .action(async (options) => {
      await integrateFoundation(options);
    });

  cssFrameworkCommand
    .command('custom')
    .description('Integrate custom CSS framework')
    .requiredOption('-c, --css-file <path>', 'Path to custom CSS file')
    .option('-o, --output <dir>', 'Output directory', './')
    .option('--no-minify', 'Disable CSS minification')
    .option('--source-maps', 'Generate source maps')
    .action(async (options) => {
      await integrateCustom(options);
    });
}

/**
 * Main CSS framework integration command
 */
async function cssFrameworkCommand(options: {
  framework: string;
  output: string;
  purge: boolean;
  content: string;
  customCss?: string;
  minify: boolean;
  sourceMaps: boolean;
  postcssPlugins?: string;
}): Promise<void> {
  logger.info(`Integrating ${options.framework} CSS framework...`);

  try {
    // Validate framework
    const validFrameworks: CSSFramework[] = ['tailwind', 'bootstrap', 'bulma', 'foundation', 'custom'];
    if (!validFrameworks.includes(options.framework as CSSFramework)) {
      throw new CLIError(
        `Invalid CSS framework: ${options.framework}`,
        ErrorType.VALIDATION,
        'CSS-001',
        [`Valid frameworks: ${validFrameworks.join(', ')}`]
      );
    }

    // Parse content paths
    const contentPaths = options.content.split(',').map(p => p.trim());

    // Parse PostCSS plugins
    const postcssPlugins = options.postcssPlugins?.split(',').map(p => p.trim()) || [];

    // Create integration options
    const integrationOptions = {
      framework: options.framework as CSSFramework,
      includeFrameworkCSS: true,
      customCSSPath: options.customCss,
      purgeUnused: options.purge,
      contentPaths,
      generateSourceMaps: options.sourceMaps,
      minify: options.minify,
      postcss: {
        plugins: postcssPlugins,
        options: {}
      }
    };

    // Initialize CSS framework integration
    const integration = new OrdoJSCSSFrameworkIntegration(integrationOptions);

    // Integrate the framework
    const result = await integration.integrate();

    if (!result.success) {
      throw new CLIError(
        `CSS framework integration failed: ${result.errors?.join(', ')}`,
        ErrorType.COMPILATION,
        'CSS-002'
      );
    }

    // Create output directory
    await fs.mkdir(options.output, { recursive: true });

    // Write CSS file
    const cssPath = path.join(options.output, result.cssPath);
    await fs.mkdir(path.dirname(cssPath), { recursive: true });
    await fs.writeFile(cssPath, result.css);

    // Generate configuration files
    const configFiles = await integration.generateConfigFiles(options.output);

    // Generate package.json dependencies
    const dependencies = integration.generateDependencies();

    // Display results
    logger.success(`✅ ${options.framework} CSS framework integrated successfully!`);
    logger.info(`📁 CSS file: ${cssPath}`);

    if (configFiles.length > 0) {
      logger.info('📁 Configuration files:');
      configFiles.forEach(file => logger.info(`   - ${file}`));
    }

    if (Object.keys(dependencies).length > 0) {
      logger.info('📦 Required dependencies:');
      Object.entries(dependencies).forEach(([pkg, version]) => {
        logger.info(`   - ${pkg}: ${version}`);
      });
    }

    // Display usage instructions
    displayUsageInstructions(options.framework as CSSFramework, cssPath);

  } catch (error) {
    if (error instanceof CLIError) {
      logger.error(`${error.type.toUpperCase()} ERROR: ${error.message}`);
      if (error.code) {
        logger.error(`Error code: ${error.code}`);
      }
      if (error.suggestions && error.suggestions.length > 0) {
        logger.info('Suggestions:');
        error.suggestions.forEach(suggestion => {
          logger.info(`  - ${suggestion}`);
        });
      }
    } else {
      logger.error(`CSS framework integration failed: ${error instanceof Error ? error.message : String(error)}`);
    }
    process.exit(1);
  }
}

/**
 * Integrate Tailwind CSS
 */
async function integrateTailwind(options: {
  output: string;
  purge: boolean;
  content: string;
  minify: boolean;
  sourceMaps: boolean;
}): Promise<void> {
  logger.info('Integrating Tailwind CSS...');

  const contentPaths = options.content.split(',').map(p => p.trim());

  const integration = new OrdoJSCSSFrameworkIntegration({
    framework: 'tailwind',
    purgeUnused: options.purge,
    contentPaths,
    minify: options.minify,
    generateSourceMaps: options.sourceMaps
  });

  const result = await integration.integrate();

  if (!result.success) {
    throw new CLIError(
      `Tailwind CSS integration failed: ${result.errors?.join(', ')}`,
      ErrorType.COMPILATION,
      'CSS-003'
    );
  }

  // Create output directory
  await fs.mkdir(options.output, { recursive: true });

  // Write CSS file
  const cssPath = path.join(options.output, result.cssPath);
  await fs.mkdir(path.dirname(cssPath), { recursive: true });
  await fs.writeFile(cssPath, result.css);

  // Generate configuration files
  const configFiles = await integration.generateConfigFiles(options.output);

  // Generate dependencies
  const dependencies = integration.generateDependencies();

  logger.success('✅ Tailwind CSS integrated successfully!');
  logger.info(`📁 CSS file: ${cssPath}`);
  logger.info('📁 Configuration files:');
  configFiles.forEach(file => logger.info(`   - ${file}`));
  logger.info('📦 Required dependencies:');
  Object.entries(dependencies).forEach(([pkg, version]) => {
    logger.info(`   - ${pkg}: ${version}`);
  });

  displayUsageInstructions('tailwind', cssPath);
}

/**
 * Integrate Bootstrap CSS
 */
async function integrateBootstrap(options: {
  output: string;
  minify: boolean;
  sourceMaps: boolean;
}): Promise<void> {
  logger.info('Integrating Bootstrap CSS...');

  const integration = new OrdoJSCSSFrameworkIntegration({
    framework: 'bootstrap',
    minify: options.minify,
    generateSourceMaps: options.sourceMaps
  });

  const result = await integration.integrate();

  if (!result.success) {
    throw new CLIError(
      `Bootstrap CSS integration failed: ${result.errors?.join(', ')}`,
      ErrorType.COMPILATION,
      'CSS-004'
    );
  }

  // Create output directory
  await fs.mkdir(options.output, { recursive: true });

  // Write CSS file
  const cssPath = path.join(options.output, result.cssPath);
  await fs.mkdir(path.dirname(cssPath), { recursive: true });
  await fs.writeFile(cssPath, result.css);

  // Generate dependencies
  const dependencies = integration.generateDependencies();

  logger.success('✅ Bootstrap CSS integrated successfully!');
  logger.info(`📁 CSS file: ${cssPath}`);
  logger.info('📦 Required dependencies:');
  Object.entries(dependencies).forEach(([pkg, version]) => {
    logger.info(`   - ${pkg}: ${version}`);
  });

  displayUsageInstructions('bootstrap', cssPath);
}

/**
 * Integrate Bulma CSS
 */
async function integrateBulma(options: {
  output: string;
  minify: boolean;
  sourceMaps: boolean;
}): Promise<void> {
  logger.info('Integrating Bulma CSS...');

  const integration = new OrdoJSCSSFrameworkIntegration({
    framework: 'bulma',
    minify: options.minify,
    generateSourceMaps: options.sourceMaps
  });

  const result = await integration.integrate();

  if (!result.success) {
    throw new CLIError(
      `Bulma CSS integration failed: ${result.errors?.join(', ')}`,
      ErrorType.COMPILATION,
      'CSS-005'
    );
  }

  // Create output directory
  await fs.mkdir(options.output, { recursive: true });

  // Write CSS file
  const cssPath = path.join(options.output, result.cssPath);
  await fs.mkdir(path.dirname(cssPath), { recursive: true });
  await fs.writeFile(cssPath, result.css);

  // Generate dependencies
  const dependencies = integration.generateDependencies();

  logger.success('✅ Bulma CSS integrated successfully!');
  logger.info(`📁 CSS file: ${cssPath}`);
  logger.info('📦 Required dependencies:');
  Object.entries(dependencies).forEach(([pkg, version]) => {
    logger.info(`   - ${pkg}: ${version}`);
  });

  displayUsageInstructions('bulma', cssPath);
}

/**
 * Integrate Foundation CSS
 */
async function integrateFoundation(options: {
  output: string;
  minify: boolean;
  sourceMaps: boolean;
}): Promise<void> {
  logger.info('Integrating Foundation CSS...');

  const integration = new OrdoJSCSSFrameworkIntegration({
    framework: 'foundation',
    minify: options.minify,
    generateSourceMaps: options.sourceMaps
  });

  const result = await integration.integrate();

  if (!result.success) {
    throw new CLIError(
      `Foundation CSS integration failed: ${result.errors?.join(', ')}`,
      ErrorType.COMPILATION,
      'CSS-006'
    );
  }

  // Create output directory
  await fs.mkdir(options.output, { recursive: true });

  // Write CSS file
  const cssPath = path.join(options.output, result.cssPath);
  await fs.mkdir(path.dirname(cssPath), { recursive: true });
  await fs.writeFile(cssPath, result.css);

  // Generate dependencies
  const dependencies = integration.generateDependencies();

  logger.success('✅ Foundation CSS integrated successfully!');
  logger.info(`📁 CSS file: ${cssPath}`);
  logger.info('📦 Required dependencies:');
  Object.entries(dependencies).forEach(([pkg, version]) => {
    logger.info(`   - ${pkg}: ${version}`);
  });

  displayUsageInstructions('foundation', cssPath);
}

/**
 * Integrate custom CSS framework
 */
async function integrateCustom(options: {
  cssFile: string;
  output: string;
  minify: boolean;
  sourceMaps: boolean;
}): Promise<void> {
  logger.info('Integrating custom CSS framework...');

  // Check if custom CSS file exists
  try {
    await fs.access(options.cssFile);
  } catch (error) {
    throw new CLIError(
      `Custom CSS file not found: ${options.cssFile}`,
      ErrorType.VALIDATION,
      'CSS-007',
      ['Check if the file exists and the path is correct']
    );
  }

  const integration = new OrdoJSCSSFrameworkIntegration({
    framework: 'custom',
    customCSSPath: options.cssFile,
    minify: options.minify,
    generateSourceMaps: options.sourceMaps
  });

  const result = await integration.integrate();

  if (!result.success) {
    throw new CLIError(
      `Custom CSS integration failed: ${result.errors?.join(', ')}`,
      ErrorType.COMPILATION,
      'CSS-008'
    );
  }

  // Create output directory
  await fs.mkdir(options.output, { recursive: true });

  // Write CSS file
  const cssPath = path.join(options.output, result.cssPath);
  await fs.mkdir(path.dirname(cssPath), { recursive: true });
  await fs.writeFile(cssPath, result.css);

  logger.success('✅ Custom CSS framework integrated successfully!');
  logger.info(`📁 CSS file: ${cssPath}`);
  logger.info(`📁 Source file: ${options.cssFile}`);

  displayUsageInstructions('custom', cssPath);
}

/**
 * Display usage instructions for the integrated framework
 */
function displayUsageInstructions(framework: CSSFramework, cssPath: string): void {
  logger.info('\n📖 Usage Instructions:');

  switch (framework) {
    case 'tailwind':
      logger.info('1. Include the CSS file in your HTML:');
      logger.info(`   <link rel="stylesheet" href="${cssPath}">`);
      logger.info('\n2. Use Tailwind classes in your OrdoJS components:');
      logger.info('   <div class="bg-blue-500 text-white p-4 rounded-lg">');
      logger.info('     Hello Tailwind!');
      logger.info('   </div>');
      logger.info('\n3. Install required dependencies:');
      logger.info('   npm install tailwindcss @tailwindcss/forms @tailwindcss/typography autoprefixer postcss');
      logger.info('\n4. Run the build process to purge unused CSS:');
      logger.info('   ordojs build src/app.ordo --minify');
      break;

    case 'bootstrap':
      logger.info('1. Include the CSS file in your HTML:');
      logger.info(`   <link rel="stylesheet" href="${cssPath}">`);
      logger.info('\n2. Use Bootstrap classes in your OrdoJS components:');
      logger.info('   <div class="container">');
      logger.info('     <div class="row">');
      logger.info('       <div class="col-md-6">Bootstrap content</div>');
      logger.info('     </div>');
      logger.info('   </div>');
      logger.info('\n3. Install Bootstrap:');
      logger.info('   npm install bootstrap');
      break;

    case 'bulma':
      logger.info('1. Include the CSS file in your HTML:');
      logger.info(`   <link rel="stylesheet" href="${cssPath}">`);
      logger.info('\n2. Use Bulma classes in your OrdoJS components:');
      logger.info('   <div class="container">');
      logger.info('     <div class="columns">');
      logger.info('       <div class="column">Bulma content</div>');
      logger.info('     </div>');
      logger.info('   </div>');
      logger.info('\n3. Install Bulma:');
      logger.info('   npm install bulma');
      break;

    case 'foundation':
      logger.info('1. Include the CSS file in your HTML:');
      logger.info(`   <link rel="stylesheet" href="${cssPath}">`);
      logger.info('\n2. Use Foundation classes in your OrdoJS components:');
      logger.info('   <div class="grid-container">');
      logger.info('     <div class="grid-x">');
      logger.info('       <div class="cell medium-6">Foundation content</div>');
      logger.info('     </div>');
      logger.info('   </div>');
      logger.info('\n3. Install Foundation:');
      logger.info('   npm install foundation-sites');
      break;

    case 'custom':
      logger.info('1. Include the CSS file in your HTML:');
      logger.info(`   <link rel="stylesheet" href="${cssPath}">`);
      logger.info('\n2. Use your custom CSS classes in OrdoJS components');
      logger.info('\n3. The custom CSS has been integrated with OrdoJS');
      break;
  }

  logger.info('\n🎨 You can now use the CSS framework classes in your OrdoJS components!');
}
