import { createPersistedProjectRecord, createPersistedWorkspaceRecord, } from "./workspace-registry.js";
import { deriveProjectGroupingName, normalizeWorkspaceId } from "./workspace-registry-model.js";
import { createWorktreeCore, } from "./worktree-core.js";
import { validateBranchSlug } from "../utils/worktree.js";
import { getCurrentBranch, localBranchExists, renameCurrentBranch } from "../utils/checkout-git.js";
import { markPaseoWorktreeFirstAgentBranchAutoNameAttempted, readPaseoWorktreeMetadata, writePaseoWorktreeFirstAgentBranchAutoNameMetadata, } from "../utils/worktree-metadata.js";
import { buildAgentBranchNameSeed } from "./agent/prompt-attachments.js";
export async function createPaseoWorktree(input, deps) {
    const createdWorktree = await createWorktreeCore(input, deps);
    maybeMarkFirstAgentBranchAutoNameEligible({ createdWorktree });
    const workspace = await upsertWorkspaceForWorktree({
        inputCwd: input.cwd,
        projectId: input.projectId,
        repoRoot: createdWorktree.repoRoot,
        worktree: createdWorktree.worktree,
        deps,
    });
    deps.github.invalidate({ cwd: createdWorktree.worktree.worktreePath });
    return {
        worktree: createdWorktree.worktree,
        intent: createdWorktree.intent,
        workspace,
        repoRoot: createdWorktree.repoRoot,
        created: createdWorktree.created,
    };
}
export async function attemptFirstAgentBranchAutoName(options) {
    const firstAgentContext = options.firstAgentContext;
    if (!firstAgentContext || !buildAgentBranchNameSeed(firstAgentContext)) {
        return { attempted: false, renamed: false, branchName: null };
    }
    let metadata;
    try {
        metadata = readPaseoWorktreeMetadata(options.cwd);
    }
    catch {
        return { attempted: false, renamed: false, branchName: null };
    }
    if (!metadata ||
        metadata.version !== 2 ||
        metadata.firstAgentBranchAutoName?.status !== "pending") {
        return { attempted: false, renamed: false, branchName: null };
    }
    const getCurrentBranchImpl = options.getCurrentBranch ?? getCurrentBranch;
    const placeholderBranchName = metadata.firstAgentBranchAutoName.placeholderBranchName;
    if ((await getCurrentBranchImpl(options.cwd)) !== placeholderBranchName) {
        markPaseoWorktreeFirstAgentBranchAutoNameAttempted(options.cwd);
        return { attempted: true, renamed: false, branchName: null };
    }
    markPaseoWorktreeFirstAgentBranchAutoNameAttempted(options.cwd);
    const branchName = await options.generateBranchNameFromContext({
        cwd: options.cwd,
        firstAgentContext,
    });
    if (!branchName) {
        return { attempted: true, renamed: false, branchName: null };
    }
    const validation = validateBranchSlug(branchName);
    if (!validation.valid || branchName === placeholderBranchName) {
        return { attempted: true, renamed: false, branchName: null };
    }
    if ((await getCurrentBranchImpl(options.cwd)) !== placeholderBranchName) {
        return { attempted: true, renamed: false, branchName: null };
    }
    const localBranchExistsImpl = options.localBranchExists ?? localBranchExists;
    const targetName = await findAvailableBranchName({
        cwd: options.cwd,
        desiredName: branchName,
        placeholderBranchName,
        localBranchExists: localBranchExistsImpl,
    });
    if (!targetName) {
        return { attempted: true, renamed: false, branchName: null };
    }
    const renameCurrentBranchImpl = options.renameCurrentBranch ?? renameCurrentBranch;
    const renamedBranch = await renameCurrentBranchImpl(options.cwd, targetName);
    return {
        attempted: true,
        renamed: true,
        branchName: renamedBranch.currentBranch ?? targetName,
    };
}
const MAX_BRANCH_NAME_SUFFIX_ATTEMPTS = 50;
async function findAvailableBranchName(options) {
    const { cwd, desiredName, placeholderBranchName } = options;
    if (!(await options.localBranchExists(cwd, desiredName))) {
        return desiredName;
    }
    for (let suffix = 2; suffix <= MAX_BRANCH_NAME_SUFFIX_ATTEMPTS; suffix++) {
        const candidate = `${desiredName}-${suffix}`;
        if (candidate === placeholderBranchName) {
            continue;
        }
        if (!(await options.localBranchExists(cwd, candidate))) {
            return candidate;
        }
    }
    return null;
}
function maybeMarkFirstAgentBranchAutoNameEligible(options) {
    const { createdWorktree } = options;
    if (!createdWorktree.created || createdWorktree.intent.kind !== "branch-off") {
        return;
    }
    writePaseoWorktreeFirstAgentBranchAutoNameMetadata(createdWorktree.worktree.worktreePath, {
        placeholderBranchName: createdWorktree.worktree.branchName,
    });
}
async function upsertWorkspaceForWorktree(options) {
    const normalizedCwd = normalizeWorkspaceId(options.worktree.worktreePath);
    const normalizedInputCwd = normalizeWorkspaceId(options.inputCwd);
    const normalizedRepoRoot = normalizeWorkspaceId(options.repoRoot);
    const existingWorkspace = await findWorkspaceByDirectory(normalizedCwd, options.deps.workspaceRegistry);
    const sourceProject = await resolveSourceProjectForWorktree({
        inputCwd: normalizedInputCwd,
        projectId: options.projectId,
        repoRoot: normalizedRepoRoot,
        existingWorkspace,
        deps: options.deps,
    });
    const workspaceId = normalizedCwd;
    const now = new Date().toISOString();
    await options.deps.projectRegistry.upsert(createPersistedProjectRecord({
        projectId: sourceProject.projectId,
        rootPath: sourceProject.rootPath,
        kind: sourceProject.kind,
        displayName: sourceProject.displayName,
        customName: sourceProject.customName,
        createdAt: sourceProject.createdAt ?? now,
        updatedAt: now,
        archivedAt: null,
    }));
    const workspace = createPersistedWorkspaceRecord({
        workspaceId,
        projectId: sourceProject.projectId,
        cwd: normalizedCwd,
        kind: "worktree",
        displayName: options.worktree.branchName || normalizedCwd,
        createdAt: existingWorkspace?.createdAt ?? now,
        updatedAt: now,
        archivedAt: null,
    });
    await options.deps.workspaceRegistry.upsert(workspace);
    return (await options.deps.workspaceRegistry.get(workspace.workspaceId)) ?? workspace;
}
function sourceProjectFromRecord(record) {
    return {
        projectId: record.projectId,
        rootPath: record.rootPath,
        kind: "git",
        displayName: record.displayName,
        customName: record.customName ?? null,
        createdAt: record.createdAt ?? null,
    };
}
async function resolveExplicitProjectForWorktree(options) {
    const project = await options.projectRegistry.get(options.projectId);
    if (!project || project.archivedAt) {
        throw new Error(`Project not found for worktree: ${options.projectId}`);
    }
    return sourceProjectFromRecord(project);
}
async function resolveWorkspaceProjectForWorktree(options) {
    const sourceProject = await options.projectRegistry.get(options.sourceWorkspace.projectId);
    return sourceProjectFromRecord({
        projectId: options.sourceWorkspace.projectId,
        rootPath: sourceProject?.rootPath ?? options.repoRoot,
        displayName: sourceProject?.displayName ?? deriveProjectGroupingName(options.sourceWorkspace.projectId),
        customName: sourceProject?.customName ?? null,
        createdAt: sourceProject?.createdAt ?? null,
    });
}
async function resolveFallbackProjectForWorktree(options) {
    const existingFallbackProject = await options.projectRegistry.get(options.repoRoot);
    return sourceProjectFromRecord({
        projectId: options.repoRoot,
        rootPath: existingFallbackProject?.rootPath ?? options.repoRoot,
        displayName: existingFallbackProject?.displayName ?? deriveProjectGroupingName(options.repoRoot),
        customName: existingFallbackProject?.customName ?? null,
        createdAt: existingFallbackProject?.createdAt ?? null,
    });
}
async function resolveSourceProjectForWorktree(options) {
    if (options.projectId) {
        return resolveExplicitProjectForWorktree({
            projectId: options.projectId,
            projectRegistry: options.deps.projectRegistry,
        });
    }
    const sourceWorkspace = options.existingWorkspace ??
        (await findWorkspaceForSource({
            inputCwd: options.inputCwd,
            repoRoot: options.repoRoot,
            workspaceRegistry: options.deps.workspaceRegistry,
        }));
    if (sourceWorkspace) {
        return resolveWorkspaceProjectForWorktree({
            sourceWorkspace,
            repoRoot: options.repoRoot,
            projectRegistry: options.deps.projectRegistry,
        });
    }
    return resolveFallbackProjectForWorktree({
        repoRoot: options.repoRoot,
        projectRegistry: options.deps.projectRegistry,
    });
}
async function findWorkspaceForSource(options) {
    const workspaces = await options.workspaceRegistry.list();
    return (workspaces.find((workspace) => workspace.cwd === options.inputCwd && !workspace.archivedAt) ??
        workspaces.find((workspace) => workspace.cwd === options.repoRoot && !workspace.archivedAt) ??
        null);
}
async function findWorkspaceByDirectory(cwd, workspaceRegistry) {
    const workspaces = await workspaceRegistry.list();
    return workspaces.find((workspace) => workspace.cwd === cwd) ?? null;
}
//# sourceMappingURL=paseo-worktree-service.js.map