/**
 * Migrate Command
 *
 * Migrates from legacy single-repo .env configuration to multi-flow config.json format.
 * Safely converts existing REPO_PATH environment variable to a flow entry.
 */
import { Command, Options } from "@effect/cli";
import { FileSystem, Path } from "@effect/platform";
// Using local types since we're writing to JSON file, not going through IPC
import { Array as Arr, Console, Data, Effect, Option, pipe } from "effect";
import * as os from "node:os";
import { ANSI, msg } from "../constants/ansi.js";
// ============================================================================
// Errors
// ============================================================================
class MigrateError extends Data.TaggedError("MigrateError") {
}
// ============================================================================
// Path Helpers
// ============================================================================
/** Get the config directory path for the current platform. */
const getConfigDir = () => {
    const home = os.homedir();
    return `${home}/Library/Application Support/ghostflow`;
};
/** Get the .env file path. */
const getEnvPath = () => `${getConfigDir()}/.env`;
/** Get the config.json file path. */
const getConfigJsonPath = () => `${getConfigDir()}/config.json`;
/** Get the .env.bak file path. */
const getEnvBackupPath = () => `${getConfigDir()}/.env.bak`;
// ============================================================================
// Options
// ============================================================================
const dryRunOption = Options.boolean("dry-run").pipe(Options.withDescription("Show what would be migrated without making changes"), Options.withDefault(false));
const forceOption = Options.boolean("force").pipe(Options.withAlias("f"), Options.withDescription("Force migration even if config.json already exists"), Options.withDefault(false));
const noBackupOption = Options.boolean("no-backup").pipe(Options.withDescription("Don't backup the .env file"), Options.withDefault(false));
// ============================================================================
// Migration Helpers
// ============================================================================
/** Parse REPO_PATH from .env content */
const parseRepoPath = (content) => {
    const lines = content.split("\n");
    const repoLine = Arr.findFirst(lines, (line) => line.startsWith("REPO_PATH="));
    return pipe(repoLine, Option.map((line) => line.substring("REPO_PATH=".length).trim()));
};
/** Generate a UUID for the new flow */
const generateFlowId = () => Effect.sync(() => crypto.randomUUID());
/** Get directory name from path */
const getFlowName = (repoPath) => Effect.gen(function* () {
    const pathService = yield* Path.Path;
    return pathService.basename(repoPath);
});
/** Create default daemon config */
const createDefaultDaemonConfig = () => ({
    pullIntervalSeconds: 30 * 60, // 30 minutes
    debounceIntervalSeconds: 2.0
});
/** Create a flow config from repo path */
const createFlowConfig = (repoPath) => Effect.gen(function* () {
    const flowId = yield* generateFlowId();
    const name = yield* getFlowName(repoPath);
    return {
        id: flowId,
        path: repoPath,
        remote: "origin",
        name,
        enabled: true
    };
});
/** Create a new GhostflowConfig from a flow */
const createGhostflowConfig = (flow) => ({
    version: 1,
    flows: [flow],
    daemon: createDefaultDaemonConfig()
});
// ============================================================================
// Migration Logic
// ============================================================================
/** Check if .env file exists and has REPO_PATH */
const checkLegacyConfig = () => Effect.gen(function* () {
    const fs = yield* FileSystem.FileSystem;
    const envPath = getEnvPath();
    const exists = yield* fs.exists(envPath);
    if (!exists) {
        return Option.none();
    }
    const content = yield* fs.readFileString(envPath);
    return parseRepoPath(content);
});
/** Check if config.json already exists */
const checkConfigJsonExists = () => Effect.gen(function* () {
    const fs = yield* FileSystem.FileSystem;
    return yield* fs.exists(getConfigJsonPath());
});
/** Backup the .env file */
const backupEnvFile = () => Effect.gen(function* () {
    const fs = yield* FileSystem.FileSystem;
    const envPath = getEnvPath();
    const backupPath = getEnvBackupPath();
    yield* fs.copy(envPath, backupPath);
});
/** Write the new config.json */
const writeConfigJson = (config) => Effect.gen(function* () {
    const fs = yield* FileSystem.FileSystem;
    const configPath = getConfigJsonPath();
    const content = JSON.stringify(config, null, 2) + "\n";
    yield* fs.writeFileString(configPath, content);
});
/** Verify the repository path is valid */
const verifyRepoPath = (repoPath) => Effect.gen(function* () {
    const fs = yield* FileSystem.FileSystem;
    // Check path exists
    const exists = yield* fs.exists(repoPath);
    if (!exists) {
        return yield* Effect.fail(new MigrateError({ message: `Repository path does not exist: ${repoPath}` }));
    }
    // Check it's a directory
    const stat = yield* fs.stat(repoPath);
    if (stat.type !== "Directory") {
        return yield* Effect.fail(new MigrateError({ message: `Repository path is not a directory: ${repoPath}` }));
    }
    // Check it has .git
    const gitPath = `${repoPath}/.git`;
    const hasGit = yield* fs.exists(gitPath);
    if (!hasGit) {
        return yield* Effect.fail(new MigrateError({ message: `Repository path is not a git repository: ${repoPath}` }));
    }
});
// ============================================================================
// Command Handler
// ============================================================================
const migrateHandler = ({ dryRun, force, noBackup }) => pipe(Effect.gen(function* () {
    yield* Console.log("Checking for legacy configuration...");
    // Check for existing .env with REPO_PATH
    const legacyPath = yield* checkLegacyConfig();
    yield* pipe(legacyPath, Option.match({
        onNone: () => Effect.gen(function* () {
            yield* Console.log("");
            yield* Console.log(msg.info("No legacy configuration found."));
            yield* Console.log(msg.info("Nothing to migrate."));
            yield* Console.log("");
            yield* Console.log("Use 'ghostflow add <path>' to add repositories.");
        }),
        onSome: (repoPath) => Effect.gen(function* () {
            yield* Console.log(`Found legacy REPO_PATH: ${repoPath}`);
            // Verify the repo path is valid
            yield* verifyRepoPath(repoPath);
            yield* Console.log(msg.success("Repository path is valid"));
            // Check if config.json already exists
            const configExists = yield* checkConfigJsonExists();
            if (configExists && !force) {
                yield* Console.error("");
                yield* Console.error(msg.warning("config.json already exists."));
                yield* Console.error("Use --force to overwrite existing configuration.");
                return yield* Effect.fail(new MigrateError({ message: "config.json already exists" }));
            }
            // Create the new flow and config
            const flow = yield* createFlowConfig(repoPath);
            const config = createGhostflowConfig(flow);
            if (dryRun) {
                yield* Console.log("");
                yield* Console.log(msg.info("Dry run - no changes made"));
                yield* Console.log("");
                yield* Console.log("Would create config.json:");
                yield* Console.log(JSON.stringify(config, null, 2));
                if (!noBackup) {
                    yield* Console.log("");
                    yield* Console.log(`Would backup .env to ${getEnvBackupPath()}`);
                }
                return;
            }
            // Backup .env if requested
            if (!noBackup) {
                yield* backupEnvFile();
                yield* Console.log(msg.success(`Backed up .env to ${getEnvBackupPath()}`));
            }
            // Write new config.json
            yield* writeConfigJson(config);
            yield* Console.log(msg.success(`Created ${getConfigJsonPath()}`));
            yield* Console.log("");
            yield* Console.log(`${ANSI.GREEN}Migration complete!${ANSI.RESET}`);
            yield* Console.log("");
            yield* Console.log("Your repository has been migrated to the new multi-flow format.");
            yield* Console.log(`  Flow ID: ${flow.id}`);
            yield* Console.log(`  Name: ${flow.name ?? "unnamed"}`);
            yield* Console.log(`  Path: ${repoPath}`);
            yield* Console.log("");
            yield* Console.log("Restart the daemon to apply changes:");
            yield* Console.log("  ghostflow restart");
        })
    }));
}), Effect.catchAll((error) => Effect.gen(function* () {
    if (error instanceof MigrateError) {
        yield* Console.error(msg.error(error.message));
    }
    else {
        yield* Console.error(msg.error(String(error)));
    }
    return yield* Effect.fail(error);
})));
// ============================================================================
// Command Definition
// ============================================================================
export const migrateCommand = Command.make("migrate", {
    dryRun: dryRunOption,
    force: forceOption,
    noBackup: noBackupOption
}).pipe(Command.withHandler(migrateHandler), Command.withDescription("Migrate from legacy .env to multi-flow config.json format"));
//# sourceMappingURL=migrate.js.map