/**
 * ============================================================
 *  src/context/sessionPath.ts —— 按目录隔离的会话文件路径
 * ------------------------------------------------------------
 *  做的事：
 *    把当前工作目录编码为 ~/.minimal-agent/sessions/<encoded>.json
 *    的文件名，让不同项目目录的对话历史互不覆盖。
 *
 *  命名规则（v2 加 sessionId 后）：
 *    <sanitized-path>-<6-hex-hash>--<sessionId>.json
 *      sanitized：路径归一化后只保留 [a-z0-9-]，最长 80 字符
 *      hash    ：原始路径 sha1 前 6 位，防 sanitize 后碰撞
 *      sessionId：v2 多 session 支持；默认 'default'
 *
 *    向后兼容：sessionId='default' 时，新文件名 `<sanitized>-<hash>--default.json`
 *    与旧文件名 `<sanitized>-<hash>.json` 都可能存在。resolveSessionFile()
 *    优先返新路径，新路径不存在但旧路径存在时回退到旧路径，保证老用户的
 *    last-context 无缝继承。
 *
 *  迁移：
 *    旧版 ~/.minimal-agent/last-context.json 启动时一次性 rename 到
 *    当前 cwd 对应的会话文件。失败静默——丢迁移好过崩进程。
 * ============================================================
 */
import { createHash } from 'node:crypto';
import { mkdir, rename, stat } from 'node:fs/promises';
import { homedir } from 'node:os';
import { dirname, join, resolve } from 'node:path';
const DEFAULT_SESSION_ID = 'default';
/**
 * 把 cwd + sessionId 编码成会话文件绝对路径。
 *
 * @param cwd 工作目录
 * @param sessionId 多 session 支持的 id；缺省 'default'
 *
 * 注意：'default' 调用走新格式 `<base>--default.json`。如果磁盘上只有
 * 旧格式 `<base>.json`（v1 历史文件），需要用 resolveSessionFile()
 * 拿到实际存在的路径用于 load。
 */
export function sessionFileFor(cwd, sessionId = DEFAULT_SESSION_ID) {
    const normalized = resolve(cwd).replace(/\\/g, '/').toLowerCase();
    const sanitized = normalized
        .replace(/:/g, '')
        .replace(/[^a-z0-9]+/g, '-')
        .replace(/^-+|-+$/g, '')
        .slice(0, 80);
    const hash = createHash('sha1').update(normalized).digest('hex').slice(0, 6);
    return join(homedir(), '.minimal-agent', 'sessions', `${sanitized}-${hash}--${sessionId}.json`);
}
/** 旧格式（v1，不带 `--<id>` 后缀）—— 仅 'default' session 可能存在 */
function legacySessionFileFor(cwd) {
    const normalized = resolve(cwd).replace(/\\/g, '/').toLowerCase();
    const sanitized = normalized
        .replace(/:/g, '')
        .replace(/[^a-z0-9]+/g, '-')
        .replace(/^-+|-+$/g, '')
        .slice(0, 80);
    const hash = createHash('sha1').update(normalized).digest('hex').slice(0, 6);
    return join(homedir(), '.minimal-agent', 'sessions', `${sanitized}-${hash}.json`);
}
/**
 * 解析 cwd + sessionId 对应的实际存在的会话文件路径。
 *
 *  - 新格式（带 `--<id>`）存在 → 返回新路径
 *  - 仅 sessionId='default' 且新路径不存在但旧路径（不带 `--`）存在 → 返回旧路径
 *  - 都不存在 → 返回新路径（让调用方按新格式 create）
 */
export async function resolveSessionFile(cwd, sessionId = DEFAULT_SESSION_ID) {
    const fresh = sessionFileFor(cwd, sessionId);
    try {
        await stat(fresh);
        return fresh;
    }
    catch {
        // 新路径不存在
    }
    if (sessionId === DEFAULT_SESSION_ID) {
        const legacy = legacySessionFileFor(cwd);
        try {
            await stat(legacy);
            return legacy;
        }
        catch {
            // 旧路径也不存在
        }
    }
    return fresh;
}
/**
 * 一次性把旧版 ~/.minimal-agent/last-context.json 迁到当前 cwd 对应的
 * 会话文件。
 *
 * 静默策略：
 *  - 旧文件不存在 → 直接返回
 *  - rename 失败（目标已存在 / 权限等）→ 忽略，旧文件原位等下次启动
 */
export async function migrateLegacyContext(cwd) {
    const legacy = join(homedir(), '.minimal-agent', 'last-context.json');
    try {
        await stat(legacy);
    }
    catch {
        return;
    }
    const target = sessionFileFor(cwd);
    try {
        await mkdir(dirname(target), { recursive: true });
        await rename(legacy, target);
    }
    catch {
        // 静默
    }
}
