"use strict";
/**
 * ClaudeDirInstaller - Manages copying .claude/ directory from package to ~/.ccs/.claude/
 * v4.1.1: Fix for npm install not copying .claude/ directory
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ClaudeDirInstaller = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const ui_1 = require("./ui");
const config_manager_1 = require("./config-manager");
// Make ora optional (might not be available during npm install postinstall)
let ora = null;
try {
    const oraModule = require('ora');
    ora = oraModule.default || oraModule;
}
catch {
    // ora not available, create fallback spinner that uses console.log with UI colors
    ora = function (text) {
        return {
            start: () => ({
                succeed: (msg) => console.log(msg || (0, ui_1.ok)(text)),
                fail: (msg) => console.log(msg || (0, ui_1.fail)(text)),
                warn: (msg) => console.log(msg || (0, ui_1.warn)(text)),
                info: (msg) => console.log(msg || (0, ui_1.info)(text)),
                text: '',
            }),
        };
    };
}
/**
 * ClaudeDirInstaller - Manages copying .claude/ directory from package to ~/.ccs/.claude/
 */
class ClaudeDirInstaller {
    constructor() {
        this.homeDir = (0, config_manager_1.getCcsHome)();
        this.ccsClaudeDir = path.join((0, config_manager_1.getCcsDir)(), '.claude');
    }
    /**
     * Copy .claude/ directory from package to ~/.ccs/.claude/
     * @param packageDir - Package installation directory (default: auto-detect)
     * @param silent - Suppress spinner output
     */
    install(packageDir, silent = false) {
        const spinner = silent || !ora ? null : ora('Copying .claude/ items to ~/.ccs/.claude/').start();
        try {
            // Auto-detect package directory if not provided
            if (!packageDir) {
                // Try to find package root by going up from this file
                packageDir = path.join(__dirname, '..', '..');
            }
            const packageClaudeDir = path.join(packageDir, '.claude');
            if (!fs.existsSync(packageClaudeDir)) {
                const msg = 'Package .claude/ directory not found';
                if (spinner) {
                    spinner.warn((0, ui_1.warn)(msg));
                    console.log(`    Searched in: ${packageClaudeDir}`);
                    console.log('    This may be a development installation');
                }
                else {
                    console.log((0, ui_1.warn)(msg));
                    console.log(`    Searched in: ${packageClaudeDir}`);
                    console.log('    This may be a development installation');
                }
                return false;
            }
            // Remove old version before copying new one
            if (fs.existsSync(this.ccsClaudeDir)) {
                if (spinner)
                    spinner.text = 'Removing old .claude/ items...';
                fs.rmSync(this.ccsClaudeDir, { recursive: true, force: true });
            }
            // Use fs.cpSync for recursive copy (Node.js 16.7.0+)
            if (spinner)
                spinner.text = 'Copying .claude/ items...';
            if (fs.cpSync) {
                fs.cpSync(packageClaudeDir, this.ccsClaudeDir, { recursive: true });
            }
            else {
                // Fallback for Node.js < 16.7.0
                this.copyDirRecursive(packageClaudeDir, this.ccsClaudeDir);
            }
            // Count files and directories
            const itemCount = this.countItems(this.ccsClaudeDir);
            const msg = `Copied .claude/ items (${itemCount.files} files, ${itemCount.dirs} directories)`;
            if (spinner) {
                spinner.succeed((0, ui_1.ok)(msg));
            }
            else {
                console.log((0, ui_1.ok)(msg));
            }
            return true;
        }
        catch (err) {
            const error = err;
            const msg = `Failed to copy .claude/ directory: ${error.message}`;
            if (spinner) {
                spinner.fail((0, ui_1.warn)(msg));
                console.warn('    CCS items may not be available');
            }
            else {
                console.warn((0, ui_1.warn)(msg));
                console.warn('    CCS items may not be available');
            }
            return false;
        }
    }
    /**
     * Recursively copy directory (fallback for Node.js < 16.7.0)
     */
    copyDirRecursive(src, dest) {
        // Create destination directory
        if (!fs.existsSync(dest)) {
            fs.mkdirSync(dest, { recursive: true });
        }
        // Read source directory
        const entries = fs.readdirSync(src, { withFileTypes: true });
        for (const entry of entries) {
            const srcPath = path.join(src, entry.name);
            const destPath = path.join(dest, entry.name);
            if (entry.isDirectory()) {
                // Recursively copy subdirectory
                this.copyDirRecursive(srcPath, destPath);
            }
            else {
                // Copy file
                fs.copyFileSync(srcPath, destPath);
            }
        }
    }
    /**
     * Count files and directories in a path
     */
    countItems(dirPath) {
        let files = 0;
        let dirs = 0;
        const countRecursive = (p) => {
            const entries = fs.readdirSync(p, { withFileTypes: true });
            for (const entry of entries) {
                if (entry.isDirectory()) {
                    dirs++;
                    countRecursive(path.join(p, entry.name));
                }
                else {
                    files++;
                }
            }
        };
        try {
            countRecursive(dirPath);
        }
        catch {
            // Ignore errors
        }
        return { files, dirs };
    }
    /**
     * Clean up deprecated files from previous installations
     * Removes ccs-delegator.md that was deprecated in v4.3.2
     */
    cleanupDeprecated(silent = false) {
        const deprecatedFile = path.join(this.ccsClaudeDir, 'agents', 'ccs-delegator.md');
        const userSymlinkFile = path.join(this.homeDir, '.claude', 'agents', 'ccs-delegator.md');
        const migrationMarker = path.join((0, config_manager_1.getCcsDir)(), '.migrations', 'v435-delegator-cleanup');
        const cleanedFiles = [];
        try {
            // Check if cleanup already done
            if (fs.existsSync(migrationMarker)) {
                return { success: true, cleanedFiles: [] }; // Already cleaned
            }
            // Clean up user symlink in ~/.claude/agents/ccs-delegator.md FIRST
            try {
                const userStats = fs.lstatSync(userSymlinkFile);
                if (userStats.isSymbolicLink()) {
                    fs.unlinkSync(userSymlinkFile);
                    cleanedFiles.push('user symlink');
                }
                else {
                    // It's not a symlink (user created their own file), backup it
                    const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T')[0];
                    const backupPath = `${userSymlinkFile}.backup-${timestamp}`;
                    fs.renameSync(userSymlinkFile, backupPath);
                    if (!silent)
                        console.log((0, ui_1.info)(`Backed up user file to ${path.basename(backupPath)}`));
                    cleanedFiles.push('user file (backed up)');
                }
            }
            catch (err) {
                const error = err;
                // File doesn't exist or other error - that's okay
                if (error.code !== 'ENOENT' && !silent) {
                    console.log((0, ui_1.warn)(`Failed to remove user symlink: ${error.message}`));
                }
            }
            // Clean up package copy in ~/.ccs/.claude/agents/ccs-delegator.md
            if (fs.existsSync(deprecatedFile)) {
                try {
                    // Check if file was modified by user (compare with expected content)
                    const shouldBackup = this.shouldBackupDeprecatedFile(deprecatedFile);
                    if (shouldBackup) {
                        const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('T')[0];
                        const backupPath = `${deprecatedFile}.backup-${timestamp}`;
                        fs.renameSync(deprecatedFile, backupPath);
                        if (!silent)
                            console.log((0, ui_1.info)(`Backed up modified deprecated file to ${path.basename(backupPath)}`));
                    }
                    else {
                        fs.rmSync(deprecatedFile, { force: true });
                    }
                    cleanedFiles.push('package copy');
                }
                catch (err) {
                    const error = err;
                    if (!silent)
                        console.log((0, ui_1.warn)(`Failed to remove package copy: ${error.message}`));
                }
            }
            // Create migration marker
            if (cleanedFiles.length > 0) {
                const migrationsDir = path.dirname(migrationMarker);
                if (!fs.existsSync(migrationsDir)) {
                    fs.mkdirSync(migrationsDir, { recursive: true, mode: 0o700 });
                }
                fs.writeFileSync(migrationMarker, new Date().toISOString());
                if (!silent) {
                    console.log((0, ui_1.ok)(`Cleaned up deprecated agent files: ${cleanedFiles.join(', ')}`));
                }
            }
            return { success: true, cleanedFiles };
        }
        catch (err) {
            const error = err;
            if (!silent)
                console.log((0, ui_1.warn)(`Cleanup failed: ${error.message}`));
            return { success: false, error: error.message, cleanedFiles };
        }
    }
    /**
     * Check if deprecated file should be backed up (user modified)
     */
    shouldBackupDeprecatedFile(filePath) {
        try {
            // Simple heuristic: if file size differs significantly from expected, assume user modified
            // Expected size for ccs-delegator.md was around 2-3KB
            const stats = fs.statSync(filePath);
            const expectedMinSize = 1000; // 1KB minimum
            const expectedMaxSize = 10000; // 10KB maximum
            // If size is outside expected range, likely user modified
            return stats.size < expectedMinSize || stats.size > expectedMaxSize;
        }
        catch {
            // If we can't determine, err on side of caution and backup
            return true;
        }
    }
    /**
     * Check if ~/.ccs/.claude/ exists and is valid
     */
    isInstalled() {
        return fs.existsSync(this.ccsClaudeDir);
    }
}
exports.ClaudeDirInstaller = ClaudeDirInstaller;
exports.default = ClaudeDirInstaller;
//# sourceMappingURL=claude-dir-installer.js.map