#!/usr/bin/env node
'use strict';

const fs = require('fs');
const path = require('path');
const os = require('os');

/**
 * CCS Postinstall Script
 * Automatically creates config files in ~/.ccs/ after npm install
 *
 * Runs when: npm install -g @kaitranntt/ccs
 * Idempotent: Safe to run multiple times (won't overwrite existing configs)
 * Cross-platform: Works on Unix, macOS, Windows
 *
 * Test isolation: Set CCS_HOME env var to redirect all operations to a test directory
 */

/**
 * Get the CCS home directory (respects CCS_HOME env var for test isolation)
 * @returns {string} Home directory path
 */
function getCcsHome() {
  return process.env.CCS_HOME || os.homedir();
}

/**
 * Check if path is a broken symlink and remove it if so
 * Fixes: ENOENT error when mkdir tries to create over a dangling symlink
 * @param {string} targetPath - Path to check
 * @returns {boolean} true if broken symlink was removed
 */
function removeIfBrokenSymlink(targetPath) {
  try {
    // lstatSync doesn't follow symlinks - it checks the link itself
    const stats = fs.lstatSync(targetPath);
    if (stats.isSymbolicLink()) {
      // Check if symlink target exists
      try {
        fs.statSync(targetPath); // This follows symlinks
        return false; // Symlink is valid
      } catch {
        // Target doesn't exist - broken symlink
        fs.unlinkSync(targetPath);
        console.log(`[!] Removed broken symlink: ${targetPath}`);
        return true;
      }
    }
    return false;
  } catch {
    // Path doesn't exist at all
    return false;
  }
}

/**
 * Validate created configuration files
 * @returns {object} { success: boolean, errors: string[], warnings: string[] }
 */
function validateConfiguration() {
  const homedir = getCcsHome();
  const errors = [];
  const warnings = [];

  // Check ~/.ccs/ directory
  const ccsDir = path.join(homedir, '.ccs');
  if (!fs.existsSync(ccsDir)) {
    errors.push('~/.ccs/ directory not found');
  }

  // Check for config file - prefer config.yaml, fallback to config.json
  const configYaml = path.join(ccsDir, 'config.yaml');
  const configJson = path.join(ccsDir, 'config.json');
  const hasConfig = fs.existsSync(configYaml) || fs.existsSync(configJson);

  if (!hasConfig) {
    errors.push('config.yaml (or config.json) not found');
  }

  // Check ~/.claude/settings.json (warning only, not critical)
  const claudeSettings = path.join(homedir, '.claude', 'settings.json');
  if (!fs.existsSync(claudeSettings)) {
    warnings.push('~/.claude/settings.json not found - run "claude /login"');
  }

  return { success: errors.length === 0, errors, warnings };
}

function createConfigFiles() {
  try {
    // Get user home directory (cross-platform, respects CCS_HOME for test isolation)
    const homedir = getCcsHome();
    const ccsDir = path.join(homedir, '.ccs');

    // Create ~/.ccs/ directory if missing
    if (fs.existsSync(ccsDir)) {
      // Check if it's a file instead of directory (edge case)
      const stats = fs.statSync(ccsDir);
      if (!stats.isDirectory()) {
        console.error('[X] ~/.ccs exists but is not a directory');
        console.error('    Remove or rename it: mv ~/.ccs ~/.ccs.bak');
        process.exit(1);
      }
    } else {
      fs.mkdirSync(ccsDir, { recursive: true, mode: 0o755 });
      console.log('[OK] Created directory: ~/.ccs/');
    }

    // Create ~/.ccs/shared/ directory structure (Phase 1)
    const sharedDir = path.join(ccsDir, 'shared');
    // Handle broken symlinks (common when upgrading from older versions)
    removeIfBrokenSymlink(sharedDir);
    if (!fs.existsSync(sharedDir)) {
      fs.mkdirSync(sharedDir, { recursive: true, mode: 0o755 });
      console.log('[OK] Created directory: ~/.ccs/shared/');
    }

    // Create shared subdirectories
    const sharedSubdirs = ['commands', 'skills', 'agents', 'plugins'];
    for (const subdir of sharedSubdirs) {
      const subdirPath = path.join(sharedDir, subdir);
      // Handle broken symlinks before creating directory
      removeIfBrokenSymlink(subdirPath);
      if (!fs.existsSync(subdirPath)) {
        fs.mkdirSync(subdirPath, { recursive: true, mode: 0o755 });
        console.log(`[OK] Created directory: ~/.ccs/shared/${subdir}/`);
      }
    }

    // Migrate from v3.1.1 to v3.2.0 (symlink architecture)
    console.log('');
    try {
      const SharedManager = require('../dist/management/shared-manager').default;
      const sharedManager = new SharedManager();
      sharedManager.migrateFromV311();
      sharedManager.ensureSharedDirectories();

      // Run v4.4 migration: Migrate instances to shared settings.json
      sharedManager.migrateToSharedSettings();
    } catch (err) {
      console.warn('[!] Migration warning:', err.message);
      console.warn('    Migration will retry on next run');
    }
    console.log('');

    // NOTE: .claude/ directory installation moved to "ccs sync" command
    // Users can run "ccs sync" to install CCS commands/skills to ~/.claude/
    // This gives users control over when to modify their Claude configuration

    // Create config.yaml if missing (primary format)
    // NOTE: gemini/codex profiles NOT included - they are added on-demand when user
    // runs `ccs gemini` or `ccs codex` for first time (requires OAuth auth first)
    // NOTE: GLM/Kimi profiles are now created via UI/CLI presets, not auto-created
    const configYamlPath = path.join(ccsDir, 'config.yaml');
    const legacyConfigPath = path.join(ccsDir, 'config.json');

    if (!fs.existsSync(configYamlPath)) {
      // Check for legacy config.json - autoMigrate() in ccs.ts will handle migration
      if (fs.existsSync(legacyConfigPath)) {
        // Validate legacy config.json before assuming migration will work
        try {
          const content = fs.readFileSync(legacyConfigPath, 'utf8');
          JSON.parse(content);
          console.log('[OK] Legacy config.json found - will migrate to config.yaml on first run');
        } catch {
          console.warn('[!] Legacy config.json is corrupted/invalid');
          console.warn('    Backup: mv ~/.ccs/config.json ~/.ccs/config.json.bak');
          console.warn('    Creating fresh config.yaml instead');
          // Fall through to create new config.yaml
          fs.renameSync(legacyConfigPath, `${legacyConfigPath}.bak`);
        }
      }

      // Create config.yaml if it doesn't exist (and legacy wasn't valid)
      if (!fs.existsSync(configYamlPath) && !fs.existsSync(legacyConfigPath)) {
        // Try to use unified config loader if dist is available
        try {
          const { saveUnifiedConfig } = require('../dist/config/unified-config-loader');
          const { createEmptyUnifiedConfig, UNIFIED_CONFIG_VERSION } = require('../dist/config/unified-config-types');

          const config = createEmptyUnifiedConfig();
          config.version = UNIFIED_CONFIG_VERSION;
          saveUnifiedConfig(config);

          console.log('[OK] Created config: ~/.ccs/config.yaml');
        } catch (loaderErr) {
          // Dist not built yet (fresh clone) - create minimal config.yaml manually
          // Wrap js-yaml require in try-catch in case it's not available
          let yaml;
          try {
            yaml = require('js-yaml');
          } catch {
            // js-yaml not available - fallback to JSON
            console.warn('[!] js-yaml not available, creating legacy config.json');
            const fallbackConfig = { profiles: {} };
            const tmpPath = `${legacyConfigPath}.tmp`;
            fs.writeFileSync(tmpPath, JSON.stringify(fallbackConfig, null, 2) + '\n', 'utf8');
            fs.renameSync(tmpPath, legacyConfigPath);
            console.log('[OK] Created config: ~/.ccs/config.json (fallback)');
            yaml = null;
          }

          if (yaml) {
            const config = {
              version: '2.0',
              profiles: {},
              accounts: {},
              cliproxy: {
                variants: {},
                oauth_accounts: {}
              },
              cliproxy_server: {
                local: {
                  port: 8317,
                  auto_start: true
                }
              }
            };

            try {
              const yamlContent = yaml.dump(config, {
                indent: 2,
                lineWidth: -1,
                noRefs: true,
                sortKeys: false
              });
              const tmpPath = `${configYamlPath}.tmp`;
              fs.writeFileSync(tmpPath, yamlContent, 'utf8');
              fs.renameSync(tmpPath, configYamlPath);
              console.log('[OK] Created config: ~/.ccs/config.yaml');
            } catch (yamlErr) {
              // Final fallback: create legacy config.json
              console.warn('[!] YAML write failed, creating legacy config.json');
              const fallbackConfig = { profiles: {} };
              const tmpPath = `${legacyConfigPath}.tmp`;
              fs.writeFileSync(tmpPath, JSON.stringify(fallbackConfig, null, 2) + '\n', 'utf8');
              fs.renameSync(tmpPath, legacyConfigPath);
              console.log('[OK] Created config: ~/.ccs/config.json (fallback)');
            }
          }
        }
      }
    } else {
      console.log('[OK] Config exists: ~/.ccs/config.yaml (preserved)');
    }

    // Warn if both config files exist (user may want to clean up)
    if (fs.existsSync(legacyConfigPath) && fs.existsSync(configYamlPath)) {
      console.log('[!] Both config.yaml and config.json exist');
      console.log('    config.json will be ignored - consider removing it');
    }

    // NOTE: GLM and Kimi profiles are NO LONGER auto-created during install
    // Users can create these via:
    //   - UI: Profile Create Dialog → Provider Presets
    //   - CLI: ccs api create --preset glm|km
    // This gives users control over which providers they want to use
    // Existing profiles are preserved for backward compatibility

    // Copy shell completion files to ~/.ccs/completions/
    const completionsDir = path.join(ccsDir, 'completions');
    const scriptsCompletionDir = path.join(__dirname, '../scripts/completion');

    if (!fs.existsSync(completionsDir)) {
      fs.mkdirSync(completionsDir, { recursive: true, mode: 0o755 });
    }

    const completionFiles = ['ccs.bash', 'ccs.zsh', 'ccs.fish', 'ccs.ps1'];
    completionFiles.forEach(file => {
      const src = path.join(scriptsCompletionDir, file);
      const dest = path.join(completionsDir, file);

      if (fs.existsSync(src)) {
        fs.copyFileSync(src, dest);
      }
    });

    console.log('[OK] Installed shell completions: ~/.ccs/completions/');
    console.log('');
    console.log('  [i] Enable auto-completion:');
    console.log('      Run: ccs --shell-completion');
    console.log('');

    // Create ~/.claude/settings.json if missing (NEW)
    const claudeDir = path.join(homedir, '.claude');
    const claudeSettingsPath = path.join(claudeDir, 'settings.json');

    if (!fs.existsSync(claudeDir)) {
      fs.mkdirSync(claudeDir, { recursive: true, mode: 0o755 });
      console.log('[OK] Created directory: ~/.claude/');
    }

    if (!fs.existsSync(claudeSettingsPath)) {
      // Create empty settings (matches Claude CLI behavior)
      const tmpPath = `${claudeSettingsPath}.tmp`;
      fs.writeFileSync(tmpPath, '{}\n', 'utf8');
      fs.renameSync(tmpPath, claudeSettingsPath);

      console.log('[OK] Created default settings: ~/.claude/settings.json');
      console.log('');
      console.log('  [i] Configure Claude CLI:');
      console.log('      Run: claude /login');
      console.log('');
    } else {
      console.log('[OK] Claude settings exist: ~/.claude/settings.json (preserved)');
    }

    // Validate configuration
    console.log('');
    console.log('[i] Validating configuration...');
    const validation = validateConfiguration();

    if (!validation.success) {
      console.error('');
      console.error('[X] Configuration validation failed:');
      validation.errors.forEach(err => console.error(`    - ${err}`));
      console.error('');
      throw new Error('Configuration incomplete');
    }

    // Show warnings (non-critical)
    if (validation.warnings.length > 0) {
      console.warn('');
      console.warn('[!] Warnings:');
      validation.warnings.forEach(warn => console.warn(`    - ${warn}`));
    }

    console.log('');
    console.log('[OK] CCS configuration ready!');
    console.log('  Run: ccs --version');

  } catch (err) {
    // Show error details
    console.error('');
    console.error('[X] CCS configuration failed');
    console.error(`    Error: ${err.message}`);
    console.error('');
    console.error('Recovery steps:');
    console.error('  1. Create directory manually:');
    console.error('     mkdir -p ~/.ccs ~/.claude');
    console.error('');
    console.error('  2. Create empty settings:');
    console.error('     echo "{}" > ~/.claude/settings.json');
    console.error('');
    console.error('  3. Retry installation:');
    console.error('     npm install -g @kaitranntt/ccs --force');
    console.error('');
    console.error('  4. If issue persists, report at:');
    console.error('     https://github.com/kaitranntt/ccs/issues');
    console.error('');

    // Exit with error code (npm will show warning)
    process.exit(1);
  }
}

// Run postinstall
createConfigFiles();
