import * as fs from 'node:fs';
import * as path from 'node:path';
import os from 'node:os';
const cache = new Map();
function resolveRoutecodexUserDir() {
    const override = process.env.ROUTECODEX_USER_DIR;
    if (override && override.trim()) {
        return override.trim();
    }
    const home = os.homedir();
    if (!home) {
        throw new Error('stopMessage file://: cannot resolve homedir');
    }
    return path.join(home, '.routecodex');
}
function resolveStopMessageFilePath(raw) {
    let text = raw.trim();
    if (!text)
        return null;
    if (text.startsWith('<') && text.endsWith('>') && text.length >= 3) {
        text = text.slice(1, -1).trim();
    }
    if (!/^file:\/\//i.test(text)) {
        return null;
    }
    const relRaw = text.slice('file://'.length).trim();
    if (!relRaw) {
        throw new Error('stopMessage file://: missing relative path');
    }
    if (relRaw.startsWith('/') || relRaw.startsWith('\\') || /^[a-zA-Z]:[\\/]/.test(relRaw)) {
        throw new Error('stopMessage file://: only supports paths relative to ~/.routecodex');
    }
    const normalizedRel = path.posix.normalize(relRaw.replace(/\\/g, '/'));
    if (!normalizedRel || normalizedRel === '.' || normalizedRel === '..' || normalizedRel.startsWith('../')) {
        throw new Error('stopMessage file://: invalid relative path');
    }
    const base = path.resolve(resolveRoutecodexUserDir());
    const abs = path.resolve(base, normalizedRel);
    if (abs !== base && !abs.startsWith(`${base}${path.sep}`)) {
        throw new Error('stopMessage file://: path escapes ~/.routecodex');
    }
    return abs;
}
export function isStopMessageFileReference(raw) {
    let text = typeof raw === 'string' ? raw.trim() : '';
    if (!text) {
        return false;
    }
    if (text.startsWith('<') && text.endsWith('>') && text.length >= 3) {
        text = text.slice(1, -1).trim();
    }
    return /^file:\/\//i.test(text);
}
export function resolveStopMessageText(raw) {
    const abs = resolveStopMessageFilePath(raw);
    if (!abs) {
        return raw;
    }
    let stat;
    try {
        stat = fs.statSync(abs);
    }
    catch (err) {
        const message = err && typeof err.message === 'string' ? err.message : String(err || 'unknown error');
        throw new Error(`stopMessage file://: cannot stat ${abs}: ${message}`);
    }
    if (!stat.isFile()) {
        throw new Error(`stopMessage file://: not a file: ${abs}`);
    }
    const existing = cache.get(abs);
    if (existing && existing.mtimeMs === stat.mtimeMs && existing.size === stat.size) {
        return existing.content;
    }
    let content;
    try {
        content = fs.readFileSync(abs, 'utf8');
    }
    catch (err) {
        const message = err && typeof err.message === 'string' ? err.message : String(err || 'unknown error');
        throw new Error(`stopMessage file://: cannot read ${abs}: ${message}`);
    }
    cache.set(abs, { mtimeMs: stat.mtimeMs, size: stat.size, content });
    return content;
}
