/**
 * Template Render Command - Render a template by ID with variables
 */

import { writeFileSync, mkdirSync } from 'fs';
import { dirname, join } from 'path';
import chalk from 'chalk';
import { logger } from '../../utils/logger.js';
import { getTemplateById, resolveTemplatePathById } from '../../core/templates/template-registry.js';
import { renderTemplate } from '../../core/templates/template-renderer.js';
import { renderHOP, listAvailableHOPs } from '../../lib/hops/hop-composer.js';

/**
 * Render HOP (Higher-Order Prompt) template command
 */
export async function hopRenderCommand(hopId, outputPath, variablesJson, options) {
  logger.header(`Rendering HOP: ${hopId}`);
  logger.blank();

  try {
    // Parse variables
    let variables = {};
    try {
      variables = JSON.parse(variablesJson || '{}');
    } catch (error) {
      logger.error('Invalid JSON in variables argument');
      logger.dim(`  ${error.message}`);
      process.exit(1);
    }

    // Add defaults
    variables.DATE = variables.DATE || new Date().toISOString().split('T')[0];
    variables.YEAR = variables.YEAR || new Date().getFullYear().toString();
    variables.TIMESTAMP = variables.TIMESTAMP || new Date().toISOString();

    // Render via hop-composer
    const frameworkRoot = join(process.cwd(), 'framework');
    const rendered = renderHOP(hopId, variables, { frameworkRoot });

    if (options?.dryRun || !outputPath) {
      logger.info(chalk.cyan('📋 HOP Preview:'));
      logger.blank();
      console.log(rendered);
      logger.blank();
      if (outputPath) logger.dim(`Would be written to: ${outputPath}`);
    } else {
      mkdirSync(dirname(outputPath), { recursive: true });
      writeFileSync(outputPath, rendered, 'utf-8');
      logger.success(`✅ HOP rendered: ${chalk.cyan(outputPath)}`);
    }
  } catch (error) {
    logger.error(`Failed to render HOP: ${error.message}`);
    process.exit(1);
  }
}

/**
 * List available HOPs
 */
export async function hopListCommand(options) {
  logger.header('Available HOPs (Higher-Order Prompts)');
  logger.blank();

  const frameworkRoot = join(process.cwd(), 'framework');
  const hops = listAvailableHOPs(frameworkRoot);

  if (hops.length === 0) {
    logger.warn('No HOPs found in framework/templates/meta-prompts/');
    return;
  }

  const byType = {};
  for (const hop of hops) {
    const type = hop.type || 'other';
    if (!byType[type]) byType[type] = [];
    byType[type].push(hop);
  }

  for (const [type, list] of Object.entries(byType)) {
    console.log(chalk.cyan(`\n  ${type.toUpperCase()}`));
    for (const hop of list) {
      console.log(`    ${chalk.white(hop.id.padEnd(30))} ${chalk.gray(hop.description || hop.path)}`);
    }
  }

  logger.blank();
  logger.dim(`Total: ${hops.length} HOPs`);
  logger.dim(`Render: morph-spec hop render <hop-id> <output-file> '<variables-json>'`);
}

/**
 * Render template command
 */
export async function templateRenderCommand(templateId, outputPath, variablesJson, options) {
  logger.header(`Rendering Template: ${templateId}`);
  logger.blank();

  try {
    // 1. Validate template exists
    const template = getTemplateById(templateId);

    if (!template) {
      logger.error(`Template not found: ${templateId}`);
      logger.dim('\n💡 Use `morph-spec template list` to see available templates');
      process.exit(1);
    }

    // 2. Resolve template path
    const projectPath = options.projectPath || process.cwd();
    const stackId = options.stack || 'blazor-azure';
    const templatePath = resolveTemplatePathById(templateId, projectPath, stackId);

    if (!templatePath) {
      logger.error(`Template file not found for ${templateId}`);
      logger.dim('  Searched in: framework/templates/ and stack templates');
      process.exit(1);
    }

    logger.dim(`Template: ${templatePath}`);

    // 3. Parse variables
    let variables = {};
    try {
      variables = JSON.parse(variablesJson);
    } catch (error) {
      logger.error('Invalid JSON in variables argument');
      logger.dim(`  ${error.message}`);
      process.exit(1);
    }

    // 4. Add default variables
    const defaults = {
      DATE: new Date().toISOString().split('T')[0],
      YEAR: new Date().getFullYear().toString(),
      TIMESTAMP: new Date().toISOString()
    };

    const allVariables = { ...defaults, ...variables };

    logger.dim(`Variables: ${Object.keys(allVariables).length} provided`);
    logger.blank();

    // 5. Render template
    const renderedContent = renderTemplate(templatePath, allVariables);

    // 6. Output
    if (options.dryRun) {
      logger.info(chalk.cyan('📋 DRY RUN - Preview (file will NOT be written)'));
      logger.blank();
      console.log(renderedContent);
      logger.blank();
      logger.dim(`Would be written to: ${outputPath}`);
    } else {
      // Create output directory if needed
      const outputDir = dirname(outputPath);
      mkdirSync(outputDir, { recursive: true });

      // Write file
      writeFileSync(outputPath, renderedContent, 'utf-8');

      logger.success(`✅ Template rendered successfully`);
      logger.dim(`  Output: ${chalk.cyan(outputPath)}`);
    }

    logger.blank();

  } catch (error) {
    logger.error(`Failed to render template: ${error.message}`);
    if (options.verbose) {
      console.error(error.stack);
    }
    process.exit(1);
  }
}
