import { readFile, writeFile, rename, unlink } from 'fs/promises';
import { tmpdir } from 'os';
import { join } from 'path';
import { getAuthProfilesFilePath, fileExists, ensureDir, getMcpcHome, getServerHost } from '../utils.js';
import { loadSessions } from '../sessions.js';
import { withFileLock } from '../file-lock.js';
import { createLogger } from '../logger.js';
import { ClientError } from '../errors.js';
import { removeKeychainOAuthClientInfo, removeKeychainOAuthTokenInfo, } from './keychain.js';
const logger = createLogger('auth-profiles');
const AUTH_PROFILES_DEFAULT_CONTENT = JSON.stringify({ profiles: {} }, null, 2);
async function loadAuthProfilesInternal() {
    const filePath = getAuthProfilesFilePath();
    if (!(await fileExists(filePath))) {
        logger.debug('Auth profiles file does not exist, returning empty profiles');
        return { profiles: {} };
    }
    try {
        const content = await readFile(filePath, 'utf-8');
        const storage = JSON.parse(content);
        if (!storage.profiles || typeof storage.profiles !== 'object') {
            logger.warn('Invalid auth profiles file format, returning empty profiles');
            return { profiles: {} };
        }
        return storage;
    }
    catch (error) {
        logger.warn(`Failed to load auth profiles: ${error.message}`);
        return { profiles: {} };
    }
}
async function saveAuthProfilesInternal(storage) {
    const filePath = getAuthProfilesFilePath();
    await ensureDir(getMcpcHome());
    const tempFile = join(tmpdir(), `mcpc-auth-profiles-${Date.now()}-${process.pid}.json`);
    try {
        const content = JSON.stringify(storage, null, 2);
        await writeFile(tempFile, content, { encoding: 'utf-8', mode: 0o600 });
        await rename(tempFile, filePath);
        logger.debug('Auth profiles saved successfully');
    }
    catch (error) {
        try {
            await unlink(tempFile);
        }
        catch {
        }
        throw new ClientError(`Failed to save auth profiles: ${error.message}`);
    }
}
export async function loadAuthProfiles() {
    const filePath = getAuthProfilesFilePath();
    return withFileLock(filePath, loadAuthProfilesInternal, AUTH_PROFILES_DEFAULT_CONTENT);
}
export async function listAuthProfiles() {
    const storage = await loadAuthProfiles();
    const profiles = [];
    for (const serverUrl in storage.profiles) {
        const serverProfiles = storage.profiles[serverUrl];
        if (serverProfiles) {
            for (const profileName in serverProfiles) {
                const profile = serverProfiles[profileName];
                if (profile) {
                    profiles.push(profile);
                }
            }
        }
    }
    return profiles;
}
export async function getAuthProfile(serverUrl, profileName) {
    const storage = await loadAuthProfiles();
    const host = getServerHost(serverUrl);
    return storage.profiles[host]?.[profileName];
}
export async function saveAuthProfile(profile) {
    const filePath = getAuthProfilesFilePath();
    return withFileLock(filePath, async () => {
        const storage = await loadAuthProfilesInternal();
        const host = getServerHost(profile.serverUrl);
        if (!storage.profiles[host]) {
            storage.profiles[host] = {};
        }
        storage.profiles[host][profile.name] = profile;
        await saveAuthProfilesInternal(storage);
        logger.debug(`Saved auth profile: ${profile.name} for ${host}`);
    }, AUTH_PROFILES_DEFAULT_CONTENT);
}
export async function updateAuthProfileRefreshedAt(serverUrl, profileName) {
    const filePath = getAuthProfilesFilePath();
    return withFileLock(filePath, async () => {
        const storage = await loadAuthProfilesInternal();
        const host = getServerHost(serverUrl);
        const profile = storage.profiles[host]?.[profileName];
        if (profile) {
            profile.refreshedAt = new Date().toISOString();
            await saveAuthProfilesInternal(storage);
            logger.debug(`Updated refreshedAt for profile: ${profileName} on ${host}`);
        }
    }, AUTH_PROFILES_DEFAULT_CONTENT);
}
export async function deleteAuthProfiles(serverUrl, profileName) {
    const filePath = getAuthProfilesFilePath();
    if (!(await fileExists(filePath))) {
        return { count: 0, affectedSessions: [] };
    }
    const deleteSpecific = serverUrl !== undefined && profileName !== undefined;
    return withFileLock(filePath, async () => {
        const storage = await loadAuthProfilesInternal();
        const profilesToDelete = [];
        if (deleteSpecific) {
            const host = getServerHost(serverUrl);
            const profile = storage.profiles[host]?.[profileName];
            if (profile) {
                profilesToDelete.push(profile);
            }
        }
        else {
            for (const host in storage.profiles) {
                const serverProfiles = storage.profiles[host];
                if (serverProfiles) {
                    for (const name in serverProfiles) {
                        const profile = serverProfiles[name];
                        if (profile) {
                            profilesToDelete.push(profile);
                        }
                    }
                }
            }
        }
        if (profilesToDelete.length === 0) {
            if (!deleteSpecific) {
                try {
                    await unlink(filePath);
                }
                catch {
                }
            }
            return { count: 0, affectedSessions: [] };
        }
        const sessionsStorage = await loadSessions();
        const affectedSessions = [];
        for (const session of Object.values(sessionsStorage.sessions)) {
            if (session.profileName && session.server.url) {
                const sessionHost = getServerHost(session.server.url);
                for (const profile of profilesToDelete) {
                    const profileHost = getServerHost(profile.serverUrl);
                    if (sessionHost === profileHost && session.profileName === profile.name) {
                        affectedSessions.push(session.name);
                        break;
                    }
                }
            }
        }
        for (const profile of profilesToDelete) {
            try {
                await removeKeychainOAuthClientInfo(profile.serverUrl, profile.name);
                await removeKeychainOAuthTokenInfo(profile.serverUrl, profile.name);
                logger.debug(`Removed keychain entries for profile: ${profile.name} on ${getServerHost(profile.serverUrl)}`);
            }
            catch (error) {
                logger.warn(`Failed to remove keychain entries for ${profile.name}:`, error);
            }
        }
        if (deleteSpecific) {
            const host = getServerHost(serverUrl);
            const serverProfiles = storage.profiles[host];
            if (serverProfiles) {
                delete serverProfiles[profileName];
                if (Object.keys(serverProfiles).length === 0) {
                    delete storage.profiles[host];
                }
            }
            await saveAuthProfilesInternal(storage);
            logger.debug(`Deleted auth profile: ${profileName} for ${host}`);
        }
        else {
            try {
                await unlink(filePath);
                logger.debug('Removed profiles.json');
            }
            catch {
            }
        }
        return { count: profilesToDelete.length, affectedSessions };
    }, AUTH_PROFILES_DEFAULT_CONTENT);
}
//# sourceMappingURL=profiles.js.map