import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
import { homedir } from "node:os";
import { dirname } from "node:path";
import * as p from "@clack/prompts";
import { colors, formatPath, messages } from "./theme.js";
/**
 * Ensure directory exists
 */
function ensureDir(dirPath) {
    if (!existsSync(dirPath)) {
        mkdirSync(dirPath, { recursive: true, mode: 0o755 });
    }
}
/**
 * Write a file, optionally skipping if exists
 */
export function writeFile(filePath, content, options = {}) {
    const exists = existsSync(filePath);
    if (exists && !options.force) {
        return { path: filePath, action: "skip" };
    }
    try {
        ensureDir(dirname(filePath));
        // Use restrictive permissions for config files
        const mode = filePath.includes(".harmony-mcp") ? 0o600 : 0o644;
        writeFileSync(filePath, content, { mode });
        return { path: filePath, action: exists ? "update" : "create" };
    }
    catch (error) {
        return {
            path: filePath,
            action: "skip",
            error: error instanceof Error ? error.message : String(error),
        };
    }
}
/**
 * Merge JSON content into existing file
 */
export function mergeJsonFile(filePath, updates, options = {}) {
    const exists = existsSync(filePath);
    if (!exists) {
        try {
            ensureDir(dirname(filePath));
            writeFileSync(filePath, JSON.stringify(updates, null, 2), {
                mode: 0o644,
            });
            return { path: filePath, action: "create" };
        }
        catch (error) {
            return {
                path: filePath,
                action: "skip",
                error: error instanceof Error ? error.message : String(error),
            };
        }
    }
    try {
        const existing = JSON.parse(readFileSync(filePath, "utf-8"));
        // Deep merge mcpServers if present (always update harmony config)
        if (updates.mcpServers && existing.mcpServers) {
            const existingServers = existing.mcpServers;
            const updateServers = updates.mcpServers;
            existing.mcpServers = { ...existingServers, ...updateServers };
        }
        else {
            Object.assign(existing, updates);
        }
        writeFileSync(filePath, JSON.stringify(existing, null, 2), { mode: 0o644 });
        return { path: filePath, action: "merge" };
    }
    catch {
        if (options.force) {
            try {
                writeFileSync(filePath, JSON.stringify(updates, null, 2), {
                    mode: 0o644,
                });
                return { path: filePath, action: "update" };
            }
            catch (error) {
                return {
                    path: filePath,
                    action: "skip",
                    error: error instanceof Error ? error.message : String(error),
                };
            }
        }
        return {
            path: filePath,
            action: "skip",
            error: "Could not parse existing file",
        };
    }
}
/**
 * Append to TOML file (for Codex config)
 */
export function appendToToml(filePath, section, content, options = {}) {
    const exists = existsSync(filePath);
    if (!exists) {
        try {
            ensureDir(dirname(filePath));
            writeFileSync(filePath, content, { mode: 0o644 });
            return { path: filePath, action: "create" };
        }
        catch (error) {
            return {
                path: filePath,
                action: "skip",
                error: error instanceof Error ? error.message : String(error),
            };
        }
    }
    try {
        const existing = readFileSync(filePath, "utf-8");
        if (existing.includes(section)) {
            if (options.force) {
                // Replace existing section
                const updated = existing.replace(new RegExp(`\\[${section.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\][\\s\\S]*?(?=\\[|$)`), content.trim() + "\n\n");
                writeFileSync(filePath, updated, { mode: 0o644 });
                return { path: filePath, action: "update" };
            }
            return { path: filePath, action: "skip" };
        }
        // Append new section
        writeFileSync(filePath, existing + "\n" + content, { mode: 0o644 });
        return { path: filePath, action: "merge" };
    }
    catch (error) {
        return {
            path: filePath,
            action: "skip",
            error: error instanceof Error ? error.message : String(error),
        };
    }
}
/**
 * Write multiple files with progress display
 */
export async function writeFilesWithProgress(files, options = {}) {
    const results = [];
    const home = homedir();
    const spinner = p.spinner();
    spinner.start("Writing configuration files...");
    for (const file of files) {
        let result;
        if (file.type === "json") {
            const jsonContent = JSON.parse(file.content);
            result = mergeJsonFile(file.path, jsonContent, options);
        }
        else if (file.type === "toml" && file.tomlSection) {
            result = appendToToml(file.path, file.tomlSection, file.content, options);
        }
        else {
            result = writeFile(file.path, file.content, options);
        }
        results.push(result);
        // Small delay for visual effect
        await new Promise((resolve) => setTimeout(resolve, 50));
    }
    spinner.stop("Files written");
    // Display results
    for (const result of results) {
        const displayPath = formatPath(result.path, home);
        if (result.error) {
            console.log(messages.fileError(displayPath, result.error));
        }
        else if (result.action === "skip") {
            console.log(messages.fileSkipped(displayPath));
        }
        else {
            const actionLabel = result.action === "merge" ? "updated" : "created";
            console.log(`  ${colors.success("\u2713")} ${colors.dim(displayPath)} ${colors.dim(`(${actionLabel})`)}`);
        }
    }
    return results;
}
/**
 * Get summary of what will be written
 */
export function getWriteSummary(files, options = {}) {
    const toCreate = [];
    const toUpdate = [];
    const toSkip = [];
    const home = homedir();
    for (const file of files) {
        const displayPath = formatPath(file.path, home);
        const exists = existsSync(file.path);
        if (exists && !options.force) {
            toSkip.push(displayPath);
        }
        else if (exists) {
            toUpdate.push(displayPath);
        }
        else {
            toCreate.push(displayPath);
        }
    }
    return { toCreate, toUpdate, toSkip };
}
