"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.ProfileRegistry = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const account_context_1 = require("./account-context");
const logging_1 = require("../services/logging");
const config_loader_facade_1 = require("../config/config-loader-facade");
const shared_resource_policy_1 = require("./shared-resource-policy");
const logger = (0, logging_1.createLogger)('auth:profile-registry');
class ProfileRegistry {
    constructor() {
        this.profilesPath = path.join((0, config_loader_facade_1.getCcsDir)(), 'profiles.json');
    }
    normalizeContextGroupValue(value) {
        if (typeof value !== 'string') {
            return undefined;
        }
        const normalized = (0, account_context_1.normalizeContextGroupName)(value);
        if (normalized.length === 0 || !(0, account_context_1.isValidContextGroupName)(normalized)) {
            return undefined;
        }
        return normalized;
    }
    normalizeLegacyProfileMetadata(metadata) {
        const normalized = { ...metadata };
        if (normalized.context_mode !== 'shared') {
            delete normalized.context_group;
            delete normalized.continuity_mode;
        }
        else {
            const normalizedGroup = this.normalizeContextGroupValue(normalized.context_group);
            if (normalizedGroup) {
                normalized.context_group = normalizedGroup;
            }
            else {
                delete normalized.context_group;
            }
            normalized.continuity_mode = normalized.continuity_mode === 'deeper' ? 'deeper' : 'standard';
        }
        return (0, shared_resource_policy_1.normalizeSharedResourceMetadata)(normalized);
    }
    normalizeUnifiedAccountConfig(account) {
        const normalized = { ...account };
        if (normalized.context_mode !== 'shared') {
            delete normalized.context_group;
            delete normalized.continuity_mode;
        }
        else {
            const normalizedGroup = this.normalizeContextGroupValue(normalized.context_group);
            if (normalizedGroup) {
                normalized.context_group = normalizedGroup;
            }
            else {
                delete normalized.context_group;
            }
            normalized.continuity_mode = normalized.continuity_mode === 'deeper' ? 'deeper' : 'standard';
        }
        return (0, shared_resource_policy_1.normalizeSharedResourceMetadata)(normalized);
    }
    /**
     * Read profiles from disk
     */
    _read() {
        if (!fs.existsSync(this.profilesPath)) {
            return {
                version: '2.0.0',
                profiles: {},
                default: null,
            };
        }
        try {
            const data = fs.readFileSync(this.profilesPath, 'utf8');
            return JSON.parse(data);
        }
        catch (error) {
            const message = error instanceof Error ? error.message : 'Unknown error';
            throw new Error(`Failed to read profiles: ${message}`);
        }
    }
    /**
     * Write profiles to disk atomically
     */
    _write(data) {
        const dir = path.dirname(this.profilesPath);
        // Ensure directory exists
        if (!fs.existsSync(dir)) {
            fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
        }
        // Atomic write: temp file + rename
        const tempPath = `${this.profilesPath}.tmp`;
        try {
            fs.writeFileSync(tempPath, JSON.stringify(data, null, 2), { mode: 0o600 });
            fs.renameSync(tempPath, this.profilesPath);
        }
        catch (error) {
            // Cleanup temp file on error
            if (fs.existsSync(tempPath)) {
                fs.unlinkSync(tempPath);
            }
            const message = error instanceof Error ? error.message : 'Unknown error';
            throw new Error(`Failed to write profiles: ${message}`);
        }
    }
    /**
     * Create a new profile
     */
    createProfile(name, metadata = {}) {
        const data = this._read();
        if (data.profiles[name]) {
            throw new Error(`Profile already exists: ${name}`);
        }
        // v3.0 minimal schema: only essential fields
        data.profiles[name] = this.normalizeLegacyProfileMetadata({
            type: metadata.type || 'account',
            created: metadata.created || new Date().toISOString(),
            last_used: metadata.last_used || null,
            context_mode: metadata.context_mode,
            context_group: metadata.context_group,
            continuity_mode: metadata.continuity_mode,
            shared_resource_mode: metadata.shared_resource_mode,
            bare: metadata.bare,
        });
        // Note: No longer auto-set as default
        // Users must explicitly run: ccs auth default <profile>
        // Default always stays on implicit 'default' profile (uses ~/.claude/)
        this._write(data);
        logger.stage('route', 'auth.profile.created', 'Profile created in registry', {
            profile: name,
            profileType: metadata.type || 'account',
        });
    }
    /**
     * Get profile metadata
     */
    getProfile(name) {
        const data = this._read();
        if (!data.profiles[name]) {
            throw new Error(`Profile not found: ${name}`);
        }
        return this.normalizeLegacyProfileMetadata(data.profiles[name]);
    }
    /**
     * Update profile metadata
     */
    updateProfile(name, updates) {
        const data = this._read();
        if (!data.profiles[name]) {
            throw new Error(`Profile not found: ${name}`);
        }
        data.profiles[name] = this.normalizeLegacyProfileMetadata({
            ...data.profiles[name],
            ...updates,
        });
        this._write(data);
    }
    /**
     * Delete a profile
     */
    deleteProfile(name) {
        const data = this._read();
        if (!data.profiles[name]) {
            throw new Error(`Profile not found: ${name}`);
        }
        delete data.profiles[name];
        // Clear default if it was the deleted profile
        if (data.default === name) {
            // Set to first remaining profile or null
            const remaining = Object.keys(data.profiles);
            data.default = remaining.length > 0 ? remaining[0] : null;
        }
        this._write(data);
        logger.stage('cleanup', 'auth.profile.deleted', 'Profile deleted from registry', {
            profile: name,
        });
    }
    /**
     * List all profiles
     */
    listProfiles() {
        const data = this._read();
        return Object.keys(data.profiles);
    }
    /**
     * Get all profiles with metadata
     */
    getAllProfiles() {
        const data = this._read();
        const normalized = {};
        for (const [name, profile] of Object.entries(data.profiles)) {
            normalized[name] = this.normalizeLegacyProfileMetadata(profile);
        }
        return normalized;
    }
    /**
     * Get default profile name
     */
    getDefaultProfile() {
        const data = this._read();
        return data.default;
    }
    /**
     * Set default profile
     */
    setDefaultProfile(name) {
        const data = this._read();
        if (!data.profiles[name]) {
            throw new Error(`Profile not found: ${name}`);
        }
        data.default = name;
        this._write(data);
    }
    /**
     * Clear default profile (restore original CCS behavior)
     */
    clearDefaultProfile() {
        const data = this._read();
        data.default = null;
        this._write(data);
    }
    /**
     * Check if profile exists
     */
    hasProfile(name) {
        const data = this._read();
        return !!data.profiles[name];
    }
    /**
     * Update last used timestamp
     */
    touchProfile(name) {
        this.updateProfile(name, {
            last_used: new Date().toISOString(),
        });
    }
    // ==========================================
    // Unified Config Methods
    // ==========================================
    /**
     * Create account in unified config (config.yaml)
     */
    createAccountUnified(name, metadata = {}) {
        (0, config_loader_facade_1.mutateConfig)((config) => {
            if (config.accounts[name]) {
                throw new Error(`Account already exists: ${name}`);
            }
            config.accounts[name] = this.normalizeUnifiedAccountConfig({
                created: new Date().toISOString(),
                last_used: null,
                context_mode: metadata.context_mode,
                context_group: metadata.context_group,
                continuity_mode: metadata.continuity_mode,
                shared_resource_mode: metadata.shared_resource_mode,
                bare: metadata.bare,
            });
        });
    }
    /**
     * Update account metadata in unified config
     */
    updateAccountUnified(name, updates) {
        (0, config_loader_facade_1.mutateConfig)((config) => {
            if (!config.accounts[name]) {
                throw new Error(`Account not found: ${name}`);
            }
            config.accounts[name] = this.normalizeUnifiedAccountConfig({
                ...config.accounts[name],
                ...updates,
            });
        });
    }
    /**
     * Remove account from unified config
     */
    removeAccountUnified(name) {
        (0, config_loader_facade_1.mutateConfig)((config) => {
            if (!config.accounts[name]) {
                throw new Error(`Account not found: ${name}`);
            }
            delete config.accounts[name];
            if (config.default === name) {
                config.default = undefined;
            }
        });
    }
    /**
     * Set default profile in unified config
     */
    setDefaultUnified(name) {
        (0, config_loader_facade_1.mutateConfig)((config) => {
            const exists = config.accounts[name] || config.profiles[name] || config.cliproxy?.variants?.[name];
            if (!exists) {
                throw new Error(`Profile not found: ${name}`);
            }
            config.default = name;
        });
    }
    /**
     * Clear default profile in unified config (restore original CCS behavior)
     */
    clearDefaultUnified() {
        (0, config_loader_facade_1.mutateConfig)((config) => {
            config.default = undefined;
        });
    }
    /**
     * Check if account exists in unified config
     */
    hasAccountUnified(name) {
        if (!(0, config_loader_facade_1.isUnifiedMode)())
            return false;
        const config = (0, config_loader_facade_1.loadOrCreateUnifiedConfig)();
        return !!config.accounts[name];
    }
    /**
     * Get all accounts from unified config
     */
    getAllAccountsUnified() {
        if (!(0, config_loader_facade_1.isUnifiedMode)())
            return {};
        const config = (0, config_loader_facade_1.loadOrCreateUnifiedConfig)();
        const normalized = {};
        for (const [name, account] of Object.entries(config.accounts)) {
            normalized[name] = this.normalizeUnifiedAccountConfig(account);
        }
        return normalized;
    }
    /**
     * Get default from unified config
     */
    getDefaultUnified() {
        if (!(0, config_loader_facade_1.isUnifiedMode)())
            return undefined;
        const config = (0, config_loader_facade_1.loadOrCreateUnifiedConfig)();
        return config.default;
    }
    /**
     * Update account last_used in unified config
     */
    touchAccountUnified(name) {
        (0, config_loader_facade_1.mutateConfig)((config) => {
            if (!config.accounts[name]) {
                throw new Error(`Account not found: ${name}`);
            }
            config.accounts[name].last_used = new Date().toISOString();
            config.accounts[name] = this.normalizeUnifiedAccountConfig(config.accounts[name]);
        });
    }
    // ==========================================
    // DRY Helper Methods (consolidated logic)
    // ==========================================
    /**
     * Get all profiles merged from both legacy and unified config.
     * Unified config takes precedence for duplicate names.
     * DRY helper to consolidate merge logic used in multiple places.
     */
    getAllProfilesMerged() {
        const legacyProfiles = this.getAllProfiles();
        const unifiedAccounts = this.getAllAccountsUnified();
        // Start with legacy profiles
        const merged = { ...legacyProfiles };
        // Override with unified config accounts (takes precedence)
        for (const [name, account] of Object.entries(unifiedAccounts)) {
            merged[name] = {
                type: 'account',
                created: account.created,
                last_used: account.last_used,
                context_mode: account.context_mode,
                context_group: account.context_group,
                continuity_mode: account.continuity_mode,
                shared_resource_mode: account.shared_resource_mode,
                bare: account.bare,
            };
        }
        return merged;
    }
    /**
     * Get resolved default profile from unified config first, fallback to legacy.
     * DRY helper to consolidate default resolution logic.
     */
    getDefaultResolved() {
        return this.getDefaultUnified() ?? this.getDefaultProfile();
    }
}
exports.ProfileRegistry = ProfileRegistry;
exports.default = ProfileRegistry;
//# sourceMappingURL=profile-registry.js.map