"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.clearConfiguredOfficialChannelTokensEverywhere = exports.clearConfiguredOfficialChannelToken = exports.setConfiguredOfficialChannelToken = exports.getOfficialChannelReadiness = exports.getOfficialChannelTokenStatus = exports.hasConfiguredOfficialChannelToken = exports.readOfficialChannelTokenFromProcessEnv = exports.readConfiguredOfficialChannelToken = exports.readOfficialChannelTokenFromEnvContent = exports.normalizeDiscordBotToken = exports.getOfficialChannelEnvPath = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const claude_config_path_1 = require("../utils/claude-config-path");
const official_channels_runtime_1 = require("./official-channels-runtime");
const config_loader_facade_1 = require("../config/config-loader-facade");
const instance_directory_1 = require("../management/instance-directory");
const MAX_OFFICIAL_CHANNEL_TOKEN_LENGTH = 4096;
function getResolvedStateDirOverride(channelId, envOverrides) {
    const env = envOverrides === undefined ? process.env : envOverrides;
    const rawStateDir = env?.[(0, official_channels_runtime_1.getOfficialChannelStateDirEnvKey)(channelId)]?.trim();
    return rawStateDir ? path.resolve(rawStateDir) : null;
}
function getOfficialChannelEnvPath(channelId, configDir = (0, claude_config_path_1.getDefaultClaudeConfigDir)(), envOverrides) {
    const overrideStateDir = getResolvedStateDirOverride(channelId, envOverrides);
    const stateDir = overrideStateDir ?? path.join(configDir, 'channels', (0, official_channels_runtime_1.getOfficialChannelEnvDir)(channelId));
    return path.join(stateDir, '.env');
}
exports.getOfficialChannelEnvPath = getOfficialChannelEnvPath;
function readFileIfExists(filePath) {
    return fs.existsSync(filePath) ? fs.readFileSync(filePath, 'utf8') : null;
}
function parseEnvValue(rawValue) {
    const value = rawValue.trim();
    if ((value.startsWith('"') && value.endsWith('"')) ||
        (value.startsWith("'") && value.endsWith("'"))) {
        return value.slice(1, -1).trim();
    }
    return value;
}
function formatEnvValue(value) {
    return /^[A-Za-z0-9._:-]+$/.test(value) ? value : JSON.stringify(value);
}
function upsertEnvValue(content, key, value) {
    const lines = content.length > 0 ? content.split(/\r?\n/) : [];
    const nextLines = [];
    let replaced = false;
    for (const line of lines) {
        if (/^\s*$/.test(line) && nextLines.length === 0) {
            continue;
        }
        if (new RegExp(`^\\s*${key}\\s*=`).test(line)) {
            nextLines.push(`${key}=${formatEnvValue(value)}`);
            replaced = true;
            continue;
        }
        nextLines.push(line);
    }
    if (!replaced) {
        if (nextLines.length > 0 && nextLines[nextLines.length - 1] !== '') {
            nextLines.push('');
        }
        nextLines.push(`${key}=${formatEnvValue(value)}`);
    }
    return `${nextLines.join('\n').replace(/\n+$/u, '')}\n`;
}
function removeEnvValue(content, key) {
    const nextLines = content
        .split(/\r?\n/)
        .filter((line) => !new RegExp(`^\\s*${key}\\s*=`).test(line));
    while (nextLines.length > 0 && /^\s*$/.test(nextLines[0] ?? '')) {
        nextLines.shift();
    }
    while (nextLines.length > 0 && /^\s*$/.test(nextLines[nextLines.length - 1] ?? '')) {
        nextLines.pop();
    }
    return nextLines.length > 0 ? `${nextLines.join('\n')}\n` : '';
}
function writeSecureFile(filePath, content) {
    fs.mkdirSync(path.dirname(filePath), { recursive: true, mode: 0o700 });
    const tempPath = `${filePath}.tmp`;
    fs.writeFileSync(tempPath, content, { encoding: 'utf8', mode: 0o600 });
    fs.renameSync(tempPath, filePath);
    fs.chmodSync(filePath, 0o600);
}
function clearOfficialChannelTokenAtPath(channelId, filePath) {
    const envKey = (0, official_channels_runtime_1.getOfficialChannelEnvKey)(channelId);
    if (!envKey) {
        return false;
    }
    const currentContent = readFileIfExists(filePath);
    if (currentContent === null) {
        return false;
    }
    const nextContent = removeEnvValue(currentContent, envKey);
    if (nextContent.length === 0) {
        fs.rmSync(filePath, { force: true });
        return true;
    }
    writeSecureFile(filePath, nextContent);
    return true;
}
function listManagedClaudeConfigDirs() {
    const dirs = new Set([(0, claude_config_path_1.getDefaultClaudeConfigDir)()]);
    const processConfigDir = process.env.CLAUDE_CONFIG_DIR?.trim();
    if (processConfigDir) {
        dirs.add(path.resolve(processConfigDir));
    }
    const instancesDir = path.join((0, config_loader_facade_1.getCcsDir)(), 'instances');
    if (!fs.existsSync(instancesDir)) {
        return [...dirs];
    }
    for (const instancePath of (0, instance_directory_1.listAccountInstancePaths)(instancesDir)) {
        dirs.add(instancePath);
    }
    return [...dirs];
}
function listManagedOfficialChannelEnvPaths(channelId) {
    const envPaths = new Set([
        getOfficialChannelEnvPath(channelId, (0, claude_config_path_1.getDefaultClaudeConfigDir)(), null),
        getOfficialChannelEnvPath(channelId),
    ]);
    for (const configDir of listManagedClaudeConfigDirs()) {
        envPaths.add(getOfficialChannelEnvPath(channelId, configDir, null));
    }
    return [...envPaths];
}
function normalizeDiscordBotToken(value) {
    const normalized = value.trim();
    if (!normalized || /[\r\n]/.test(normalized)) {
        return null;
    }
    return normalized;
}
exports.normalizeDiscordBotToken = normalizeDiscordBotToken;
function readOfficialChannelTokenFromEnvContent(channelId, content) {
    const envKey = (0, official_channels_runtime_1.getOfficialChannelEnvKey)(channelId);
    if (!envKey) {
        return null;
    }
    for (const line of content.split(/\r?\n/)) {
        const match = line.match(new RegExp(`^\\s*${envKey}\\s*=\\s*(.*)\\s*$`));
        if (!match) {
            continue;
        }
        const parsed = parseEnvValue(match[1] ?? '');
        return parsed.length > 0 ? parsed : null;
    }
    return null;
}
exports.readOfficialChannelTokenFromEnvContent = readOfficialChannelTokenFromEnvContent;
function readConfiguredOfficialChannelToken(channelId) {
    const content = readFileIfExists(getOfficialChannelEnvPath(channelId));
    return content ? readOfficialChannelTokenFromEnvContent(channelId, content) : null;
}
exports.readConfiguredOfficialChannelToken = readConfiguredOfficialChannelToken;
function readOfficialChannelTokenFromProcessEnv(channelId, envOverrides) {
    const envKey = (0, official_channels_runtime_1.getOfficialChannelEnvKey)(channelId);
    if (!envKey) {
        return null;
    }
    const rawValue = (envOverrides === undefined ? process.env : envOverrides)?.[envKey];
    if (typeof rawValue !== 'string') {
        return null;
    }
    return normalizeDiscordBotToken(rawValue);
}
exports.readOfficialChannelTokenFromProcessEnv = readOfficialChannelTokenFromProcessEnv;
function hasConfiguredOfficialChannelToken(channelId) {
    return readConfiguredOfficialChannelToken(channelId) !== null;
}
exports.hasConfiguredOfficialChannelToken = hasConfiguredOfficialChannelToken;
function getOfficialChannelTokenStatus(channelId, envOverrides) {
    const envKey = (0, official_channels_runtime_1.getOfficialChannelEnvKey)(channelId);
    if (!envKey) {
        return {
            available: true,
            source: 'saved_env',
            savedInClaudeState: true,
            processEnvAvailable: false,
        };
    }
    const processEnvToken = readOfficialChannelTokenFromProcessEnv(channelId, envOverrides);
    const tokenPath = getOfficialChannelEnvPath(channelId);
    const savedToken = readConfiguredOfficialChannelToken(channelId);
    if (savedToken !== null) {
        return {
            available: true,
            source: 'saved_env',
            envKey,
            tokenPath,
            savedInClaudeState: true,
            processEnvAvailable: processEnvToken !== null,
        };
    }
    if (processEnvToken !== null) {
        return {
            available: true,
            source: 'process_env',
            envKey,
            savedInClaudeState: false,
            processEnvAvailable: true,
        };
    }
    return {
        available: false,
        source: 'missing',
        envKey,
        tokenPath,
        savedInClaudeState: false,
        processEnvAvailable: false,
    };
}
exports.getOfficialChannelTokenStatus = getOfficialChannelTokenStatus;
function getOfficialChannelReadiness(channelId) {
    return (0, official_channels_runtime_1.isOfficialChannelTokenRequired)(channelId)
        ? getOfficialChannelTokenStatus(channelId).available
        : true;
}
exports.getOfficialChannelReadiness = getOfficialChannelReadiness;
function setConfiguredOfficialChannelToken(channelId, token) {
    const envKey = (0, official_channels_runtime_1.getOfficialChannelEnvKey)(channelId);
    if (!envKey) {
        throw new Error(`${channelId} does not use a bot token.`);
    }
    const normalized = normalizeDiscordBotToken(token);
    if (!normalized) {
        throw new Error(`${envKey} cannot be empty or multiline.`);
    }
    if (normalized.length > MAX_OFFICIAL_CHANNEL_TOKEN_LENGTH) {
        throw new Error(`${envKey} cannot exceed ${MAX_OFFICIAL_CHANNEL_TOKEN_LENGTH} characters.`);
    }
    const envPath = getOfficialChannelEnvPath(channelId);
    const currentContent = readFileIfExists(envPath) ?? '';
    writeSecureFile(envPath, upsertEnvValue(currentContent, envKey, normalized));
    return envPath;
}
exports.setConfiguredOfficialChannelToken = setConfiguredOfficialChannelToken;
function clearConfiguredOfficialChannelToken(channelId) {
    const envPath = getOfficialChannelEnvPath(channelId);
    clearOfficialChannelTokenAtPath(channelId, envPath);
    return envPath;
}
exports.clearConfiguredOfficialChannelToken = clearConfiguredOfficialChannelToken;
function clearConfiguredOfficialChannelTokensEverywhere(channelId) {
    const clearedPaths = [];
    const channels = channelId ? [channelId] : (0, official_channels_runtime_1.getOfficialChannelTokenIds)();
    for (const tokenChannelId of channels) {
        for (const envPath of listManagedOfficialChannelEnvPaths(tokenChannelId)) {
            if (clearOfficialChannelTokenAtPath(tokenChannelId, envPath)) {
                clearedPaths.push(envPath);
            }
        }
    }
    return clearedPaths;
}
exports.clearConfiguredOfficialChannelTokensEverywhere = clearConfiguredOfficialChannelTokensEverywhere;
//# sourceMappingURL=official-channels-store.js.map