"use client";
import { useCallback, useEffect, useState } from "react";
import { getUserMessage } from "@stigmer/sdk";
import { useDefaultAgent } from "../agent";
import { useModelRegistry } from "../models";
import { parseModelKey } from "../models/registry";
import { DEFAULT_HARNESS } from "../models/harness";
import { useWorkspaceEntries } from "../workspace";
import { useSessionVariables } from "../execution/useSessionVariables";
import { useCreateSession } from "./useCreateSession";
import { useCreateAgentExecution } from "../execution/useCreateAgentExecution";
const STORAGE_KEY_HARNESS = "stigmer:session:harness";
const STORAGE_KEY_RUNNER = "stigmer:session:runner";
function modelStorageKey(harness) {
    return harness === "cursor"
        ? "stigmer:session:model:cursor"
        : "stigmer:session:model";
}
/**
 * Orchestrates the "create a new session" flow.
 *
 * Manages all the state required to configure and submit a new session:
 * model selection (with localStorage persistence), agent resolution,
 * MCP server/skill/runner selection, workspace entries, and session
 * variables. On submission, creates the session and its first execution
 * in sequence, then notifies the consumer via `onSessionCreated`.
 *
 * This hook is framework-agnostic — it works identically in Next.js,
 * Vite, Tauri, or any React environment. Navigation, toast notifications,
 * and draft-mode logic are the consumer's responsibility.
 *
 * @example
 * ```tsx
 * const flow = useNewSessionFlow({
 *   org: "acme",
 *   onSessionCreated: (id) => navigate(`/sessions/${id}`),
 *   onError: (msg) => toast.error(msg),
 * });
 *
 * <SessionComposer
 *   onSubmit={flow.submit}
 *   isSubmitting={flow.isSubmitting}
 *   org="acme"
 *   workspace={flow.workspace}
 *   agentRef={flow.agentRef}
 *   onAgentRefChange={flow.setAgentRef}
 *   onAgentResolutionChange={flow.setResolution}
 *   mcpServerUsages={flow.mcpServerUsages}
 *   onMcpServerUsagesChange={flow.setMcpServerUsages}
 *   skillRefs={flow.skillRefs}
 *   onSkillRefsChange={flow.setSkillRefs}
 *   runnerId={flow.runnerId}
 *   onRunnerIdChange={flow.setRunnerId}
 *   sessionVariables={flow.sessionVariables}
 *   defaultModelId={flow.modelId}
 *   onModelChange={flow.setModelId}
 * />
 * ```
 */
export function useNewSessionFlow(options) {
    const { org, onSessionCreated, onError } = options;
    const [harness, setHarnessRaw] = useState(() => {
        if (typeof window === "undefined")
            return DEFAULT_HARNESS;
        const stored = localStorage.getItem(STORAGE_KEY_HARNESS);
        return stored === "cursor" ? "cursor" : DEFAULT_HARNESS;
    });
    const { getModel } = useModelRegistry({ harness });
    const { create: createSession } = useCreateSession();
    const { create: createExecution } = useCreateAgentExecution();
    const { agent: defaultAgent, isLoading: isDefaultAgentLoading, error: defaultAgentError, } = useDefaultAgent(org);
    const workspace = useWorkspaceEntries();
    const sessionVariables = useSessionVariables();
    const [modelId, setModelId] = useState(undefined);
    const [agentRef, setAgentRef] = useState(null);
    const [resolution, setResolution] = useState(null);
    const [mcpServerUsages, setMcpServerUsages] = useState([]);
    const [skillRefs, setSkillRefs] = useState([]);
    const [runnerId, setRunnerId] = useState(null);
    const [isSubmitting, setIsSubmitting] = useState(false);
    const [submitError, setSubmitError] = useState(null);
    const validModelId = modelId && getModel(modelId) ? modelId : undefined;
    // Persist harness on change
    useEffect(() => {
        localStorage.setItem(STORAGE_KEY_HARNESS, harness);
    }, [harness]);
    const setHarness = useCallback((h) => {
        setHarnessRaw(h);
        const storedModel = localStorage.getItem(modelStorageKey(h));
        const plain = storedModel ? (parseModelKey(storedModel)?.modelId ?? storedModel) : undefined;
        setModelId(plain);
    }, []);
    // Restore persisted model on mount (using current harness key)
    useEffect(() => {
        const stored = localStorage.getItem(modelStorageKey(harness));
        if (stored) {
            const plain = parseModelKey(stored)?.modelId ?? stored;
            if (getModel(plain)) {
                setModelId(plain);
            }
        }
    }, [getModel, harness]);
    // Persist model on change (using current harness key).
    // Strip compound keys (e.g. "cursor/default") to plain modelId before storing.
    useEffect(() => {
        if (modelId) {
            const plain = parseModelKey(modelId)?.modelId ?? modelId;
            localStorage.setItem(modelStorageKey(harness), plain);
        }
    }, [modelId, harness]);
    // Restore persisted runner on mount
    useEffect(() => {
        const stored = localStorage.getItem(STORAGE_KEY_RUNNER);
        if (stored) {
            setRunnerId(stored);
        }
    }, []);
    // Persist runner on change
    useEffect(() => {
        if (runnerId) {
            localStorage.setItem(STORAGE_KEY_RUNNER, runnerId);
        }
        else {
            localStorage.removeItem(STORAGE_KEY_RUNNER);
        }
    }, [runnerId]);
    const submit = useCallback(async (message, selectedModel, context) => {
        if (isSubmitting)
            return;
        if (!org) {
            const msg = "Select an organization before starting a session.";
            setSubmitError(msg);
            onError?.(msg);
            return;
        }
        setIsSubmitting(true);
        setSubmitError(null);
        try {
            const sessionFields = {
                org,
                workspaceEntries: workspace.hasEntries
                    ? workspace.toInput()
                    : undefined,
                mcpServerUsages: mcpServerUsages.length > 0 ? mcpServerUsages : undefined,
                skillRefs: skillRefs.length > 0 ? skillRefs : undefined,
                runnerId: runnerId ?? undefined,
                harness,
            };
            const executionFields = {
                org,
                message,
                modelName: selectedModel ?? validModelId,
                runtimeEnv: context?.runtimeEnv,
                attachments: context?.attachments,
            };
            let sessionId;
            if (agentRef && resolution) {
                if (resolution.mode === "saved") {
                    ({ sessionId } = await createSession({
                        ...sessionFields,
                        agentInstanceId: resolution.instanceId,
                    }));
                }
                else {
                    ({ sessionId } = await createSession({
                        ...sessionFields,
                        agentRef,
                    }));
                }
            }
            else {
                const defaultInstanceId = defaultAgent?.status?.defaultInstanceId;
                if (!defaultInstanceId) {
                    if (isDefaultAgentLoading) {
                        throw new Error("Loading default agent. Please try again in a moment.");
                    }
                    if (defaultAgentError) {
                        throw new Error("Failed to load default agent. Please try again.");
                    }
                    throw new Error("No default agent available. Select an agent to start a session.");
                }
                ({ sessionId } = await createSession({
                    ...sessionFields,
                    agentInstanceId: defaultInstanceId,
                }));
            }
            await createExecution({ ...executionFields, sessionId });
            sessionVariables.clear();
            onSessionCreated(sessionId);
        }
        catch (err) {
            const detail = getUserMessage(err, "Failed to start session");
            setSubmitError(detail);
            onError?.(detail);
        }
        finally {
            setIsSubmitting(false);
        }
    }, [
        isSubmitting,
        org,
        harness,
        validModelId,
        workspace,
        mcpServerUsages,
        skillRefs,
        runnerId,
        agentRef,
        resolution,
        defaultAgent,
        isDefaultAgentLoading,
        defaultAgentError,
        createSession,
        createExecution,
        sessionVariables,
        onSessionCreated,
        onError,
    ]);
    return {
        harness,
        setHarness,
        modelId: validModelId,
        setModelId,
        agentRef,
        setAgentRef,
        resolution,
        setResolution,
        mcpServerUsages,
        setMcpServerUsages,
        skillRefs,
        setSkillRefs,
        runnerId,
        setRunnerId,
        workspace,
        sessionVariables,
        isSubmitting,
        submitError,
        submit,
    };
}
//# sourceMappingURL=useNewSessionFlow.js.map