/**
 * @fileoverview FileWriter - Saves generated configs to filesystem
 * @module morph-spec/writer/file-writer
 */

import { writeFile, mkdir, access } from 'fs/promises';
import { join, dirname } from 'path';
import chalk from 'chalk';

/**
 * @typedef {import('../types/index.js').GeneratedConfigs} GeneratedConfigs
 */

/**
 * FileWriter - Saves configuration files to .morph/ directory
 * @class
 */
export class FileWriter {
  /**
   * Save generated configs to filesystem
   * @param {string} cwd - Current working directory
   * @param {GeneratedConfigs} configs - Configs to save
   * @returns {Promise<void>}
   */
  async save(cwd, configs) {
    const morphDir = join(cwd, '.morph');
    const configDir = join(morphDir, 'config');

    // Ensure directories exist
    await this.ensureDirectoryExists(morphDir);
    await this.ensureDirectoryExists(configDir);

    // Write files
    const projectMdPath = join(morphDir, 'project.md');
    const configJsonPath = join(configDir, 'config.json');

    await Promise.all([
      this.writeProjectMd(projectMdPath, configs.projectMd),
      this.writeConfigJson(configJsonPath, configs.configJson)
    ]);

    // Display success message
    console.log(chalk.bold.green('\n✅ Configuration files saved:\n'));
    console.log(chalk.cyan(`  📄 ${projectMdPath}`));
    console.log(chalk.cyan(`  ⚙️  ${configJsonPath}`));
    console.log();
  }

  /**
   * Write project.md file
   * @param {string} filepath - File path
   * @param {string} content - File content
   * @returns {Promise<void>}
   */
  async writeProjectMd(filepath, content) {
    await writeFile(filepath, content, 'utf-8');
  }

  /**
   * Write config.json file (with pretty formatting)
   * @param {string} filepath - File path
   * @param {string} content - File content (JSON string)
   * @returns {Promise<void>}
   */
  async writeConfigJson(filepath, content) {
    // Parse and re-stringify with pretty formatting
    const parsed = JSON.parse(content);
    const formatted = JSON.stringify(parsed, null, 2);

    await writeFile(filepath, formatted, 'utf-8');
  }

  /**
   * Ensure directory exists (create if not)
   * @param {string} dirPath - Directory path
   * @returns {Promise<void>}
   */
  async ensureDirectoryExists(dirPath) {
    try {
      await access(dirPath);
    } catch (error) {
      // Directory doesn't exist, create it
      await mkdir(dirPath, { recursive: true });
    }
  }
}
