import { spawn } from "node:child_process";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
import { CONTROL_PLANE_HOST, CONTROL_PLANE_PORT } from "@pocketcoder/shared";
import { readPidFile, isProcessRunning } from "../../utils/pid.js";
import { loadTokens } from "../../auth/token-storage.js";
import { login, setGetOAuthUrlFn } from "../../auth/login.js";
import { getEnv } from "../../env.js";
/**
 * Check if the daemon is already running by:
 * 1. Reading the PID file and checking if the process exists
 * 2. Hitting the /healthz endpoint to confirm it's responsive
 */
export async function isDaemonRunning() {
    const pid = await readPidFile();
    if (pid === null || !isProcessRunning(pid)) {
        return false;
    }
    // PID exists and process is alive — verify via healthz
    try {
        const url = `http://${CONTROL_PLANE_HOST}:${CONTROL_PLANE_PORT}/healthz`;
        const response = await fetch(url, { signal: AbortSignal.timeout(2000) });
        if (response.ok) {
            const body = (await response.json());
            return body.status === "ok";
        }
        return false;
    }
    catch {
        return false;
    }
}
/**
 * Handle the `pocketcoder start` CLI command.
 * Starts the daemon in background (default) or foreground mode.
 */
export async function startCommand(options) {
    // Check if daemon is already running
    const running = await isDaemonRunning();
    if (running) {
        console.log("Daemon is already running");
        return;
    }
    if (options.foreground) {
        console.log("Starting daemon in foreground...");
        // In foreground mode, we dynamically import and run the daemon directly.
        // The daemon module (US-DAEMON-045) will handle the full startup sequence.
        // For now, we import it if it exists; this will be wired up when daemon.ts is created.
        try {
            const { startDaemon } = await import("../../daemon.js");
            await startDaemon();
        }
        catch (err) {
            const message = err instanceof Error ? err.message : String(err);
            console.error(`Failed to start daemon: ${message}`);
            process.exitCode = 1;
        }
    }
    else {
        // In background mode, check auth before spawning daemon
        // This provides interactive login with user feedback
        const tokens = await loadTokens();
        if (!tokens) {
            console.log("No session found. Starting login...");
            // Configure OAuth URL provider
            const { supabaseUrl } = getEnv();
            setGetOAuthUrlFn(async (redirectTo) => {
                const url = new URL(`${supabaseUrl}/auth/v1/authorize`);
                url.searchParams.set("provider", "github");
                url.searchParams.set("redirect_to", redirectTo);
                url.searchParams.set("response_type", "code");
                return url.toString();
            });
            console.log("Opening browser for GitHub authentication in 5 seconds...");
            await new Promise((resolve) => setTimeout(resolve, 5000));
            try {
                const result = await login();
                const displayName = result.email ?? result.user_id;
                console.log(`Logged in as ${displayName}`);
            }
            catch (err) {
                const message = err instanceof Error ? err.message : String(err);
                console.error(`Login failed: ${message}`);
                process.exitCode = 1;
                return;
            }
        }
        console.log("Starting daemon...");
        // Daemonize: spawn a detached child process running in foreground mode
        const cliPath = join(dirname(fileURLToPath(import.meta.url)), "..", "index.js");
        const child = spawn(process.execPath, [cliPath, "start", "--foreground"], {
            detached: true,
            stdio: "ignore",
            env: process.env, // Pass through environment variables (e.g., GATEWAY_URL)
        });
        child.unref();
        // Wait for daemon to be ready (poll healthz endpoint)
        const maxWaitMs = 30_000;
        const pollIntervalMs = 500;
        const startTime = Date.now();
        let ready = false;
        while (Date.now() - startTime < maxWaitMs) {
            await new Promise((resolve) => setTimeout(resolve, pollIntervalMs));
            // Check if child process is still alive
            if (child.pid && !isProcessRunning(child.pid)) {
                console.error("Daemon failed to start (process exited)");
                console.error("Run 'pocketcoder logs' for details");
                process.exitCode = 1;
                return;
            }
            // Check if daemon is responding
            if (await isDaemonRunning()) {
                ready = true;
                break;
            }
        }
        if (ready) {
            console.log(`Daemon started (PID: ${child.pid})`);
        }
        else {
            console.error("Daemon failed to start (timeout waiting for healthz)");
            console.error("Run 'pocketcoder logs' for details");
            process.exitCode = 1;
        }
    }
}
//# sourceMappingURL=start.js.map