/**
 * Start Command
 *
 * Starts the Ghostflow daemon via launchd.
 * Automatically runs first-time setup if needed.
 */
import { Command, Options } from "@effect/cli";
import { LaunchdService } from "@ghostflow/client";
import { Array as Arr, Console, Data, Effect, Option } from "effect";
import { msg } from "../constants/ansi.js";
import { resolveDaemonPath, validateDaemonPath } from "../resolver.js";
import { ensureSetup } from "../setup.js";
// ============================================================================
// Errors
// ============================================================================
class StartError extends Data.TaggedError("StartError") {
}
// ============================================================================
// Options
// ============================================================================
const daemonPathOption = Options.text("daemon-path").pipe(Options.withAlias("d"), Options.withDescription("Path to the daemon binary (auto-detected if not specified)"), Options.optional);
// ============================================================================
// Display Helpers
// ============================================================================
/** Convert boolean flag to Option with message */
const flagToMessage = (flag, message) => flag ? Option.some(message) : Option.none();
/** Display setup results if any changes were made */
const displaySetupResults = (result) => {
    const changes = Arr.getSomes([
        flagToMessage(result.configCreated, "Created config directory"),
        flagToMessage(result.envCreated, "Saved repository configuration"),
        flagToMessage(result.plistCreated, "Generated launchd configuration")
    ]);
    return Arr.match(changes, {
        onEmpty: () => Effect.void,
        onNonEmpty: (items) => Effect.gen(function* () {
            yield* Console.log("");
            yield* Effect.forEach(items, (message) => Console.log(msg.success(message)), { discard: true });
            yield* Console.log("");
        })
    });
};
// ============================================================================
// Command Implementation
// ============================================================================
/** Resolve daemon path from option or auto-detect */
const resolvePath = (daemonPath) => Option.match(daemonPath, {
    onNone: () => resolveDaemonPath(),
    onSome: (path) => validateDaemonPath(path)
});
/** Check if daemon is already running and report status */
const checkAlreadyRunning = (launchd) => Effect.gen(function* () {
    const status = yield* launchd.status();
    yield* Effect.when(Effect.gen(function* () {
        yield* Console.log(msg.warning("Ghostflow daemon is already running"));
        yield* Console.log(`  PID: ${status.pid}`);
    }), () => status.isRunning);
    return status.isRunning;
});
/** Start the daemon and verify it started successfully */
const startAndVerify = (launchd, resolvedPath) => Effect.gen(function* () {
    yield* Console.log("Starting Ghostflow daemon...");
    // Load via launchd (plist was already generated by ensureSetup)
    yield* launchd.load({
        daemonPath: resolvedPath,
        workingDirectory: undefined,
        environment: undefined
    });
    // Verify it started
    yield* Effect.sleep("1 second");
    const newStatus = yield* launchd.status();
    yield* Effect.if(newStatus.isRunning, {
        onTrue: () => Console.log(msg.running(`Ghostflow daemon started (PID: ${newStatus.pid})`)),
        onFalse: () => Effect.gen(function* () {
            yield* Console.error(msg.stopped("Daemon failed to start"));
            yield* Console.error("Check logs at: ~/Library/Logs/ghostflow/daemon.log");
            yield* Effect.fail(new StartError({ message: "Daemon failed to start" }));
        })
    });
});
const startHandler = ({ daemonPath }) => Effect.gen(function* () {
    const launchd = yield* LaunchdService;
    // Resolve daemon path first (validate user-provided paths for security)
    const resolvedPath = yield* resolvePath(daemonPath);
    // Run first-time setup if needed (creates config dir, prompts for repo path, generates plist)
    const setupResult = yield* ensureSetup(resolvedPath);
    yield* displaySetupResults(setupResult);
    // Check if already running - only start if not already running
    const alreadyRunning = yield* checkAlreadyRunning(launchd);
    yield* Effect.unless(startAndVerify(launchd, resolvedPath), () => alreadyRunning);
}).pipe(Effect.tapError((error) => Console.error(msg.error(String(error)))));
// ============================================================================
// Command Definition
// ============================================================================
export const startCommand = Command.make("start", { daemonPath: daemonPathOption }).pipe(Command.withHandler(startHandler), Command.withDescription("Start the Ghostflow daemon"));
//# sourceMappingURL=start.js.map