import fs from 'fs/promises';
import path from 'path';
import crypto from 'crypto';
export class ConfigManager {
    constructor(logger) {
        this.logger = logger;
        this.configPath = path.join(process.cwd(), 'data', 'config.json');
        this.config = this.getDefaultConfig();
    }
    getDefaultConfig() {
        return {
            jwt: {
                secret: this.generateJWTSecret(),
                expiresIn: '24h'
            },
            auth: {
                maxLoginAttempts: 5,
                lockoutDuration: 15 * 60 * 1000,
                sessionTimeout: 24 * 60 * 60 * 1000
            },
            security: {
                tokenResetRule: 'startup',
                tokenExpireHours: 24
            },
            server: {
                port: parseInt(process.env.PORT || '3001', 10),
                host: process.env.HOST || '0.0.0.0',
                corsOrigin: process.env.CLIENT_URL || 'http://localhost:3000'
            },
            steamcmd: {
                installMode: 'online',
                installPath: '',
                isInstalled: false
            },
            terminal: {
                defaultUser: ''
            },
            game: {
                defaultInstallPath: ''
            }
        };
    }
    generateJWTSecret() {
        return crypto.randomBytes(64).toString('hex');
    }
    async initialize() {
        try {
            const dataDir = path.dirname(this.configPath);
            await fs.mkdir(dataDir, { recursive: true });
            await this.loadConfig();
            await this.checkAndResetTokenOnStartup();
            this.logger.info('配置管理器初始化完成');
        }
        catch (error) {
            this.logger.error('配置管理器初始化失败:', error);
            throw error;
        }
    }
    async loadConfig() {
        try {
            const configData = await fs.readFile(this.configPath, 'utf-8');
            const savedConfig = JSON.parse(configData);
            this.config = this.mergeConfig(this.getDefaultConfig(), savedConfig);
            this.logger.info('配置文件加载成功');
        }
        catch (error) {
            if (error.code === 'ENOENT') {
                this.logger.info('配置文件不存在，创建新的配置文件');
                await this.saveConfig();
            }
            else {
                this.logger.error('加载配置文件失败:', error);
                throw error;
            }
        }
    }
    mergeConfig(defaultConfig, savedConfig) {
        return {
            jwt: {
                ...defaultConfig.jwt,
                ...savedConfig.jwt
            },
            auth: {
                ...defaultConfig.auth,
                ...savedConfig.auth
            },
            security: {
                ...defaultConfig.security,
                ...savedConfig.security
            },
            server: {
                ...defaultConfig.server,
                ...savedConfig.server
            },
            steamcmd: {
                ...defaultConfig.steamcmd,
                ...savedConfig.steamcmd
            },
            terminal: {
                ...defaultConfig.terminal,
                ...savedConfig.terminal
            },
            game: {
                ...defaultConfig.game,
                ...savedConfig.game
            },
            sponsor: savedConfig.sponsor ? {
                ...savedConfig.sponsor
            } : undefined,
            developer: savedConfig.developer ? {
                ...savedConfig.developer
            } : undefined
        };
    }
    async saveConfig() {
        try {
            await fs.writeFile(this.configPath, JSON.stringify(this.config, null, 2), 'utf-8');
            this.logger.info('配置文件保存成功');
        }
        catch (error) {
            this.logger.error('保存配置文件失败:', error);
            throw error;
        }
    }
    getConfig() {
        return { ...this.config };
    }
    async updateConfig(updates) {
        this.config = this.mergeConfig(this.config, updates);
        await this.saveConfig();
    }
    async regenerateJWTSecret() {
        this.config.jwt.secret = this.generateJWTSecret();
        await this.saveConfig();
        this.logger.info('JWT密钥已重新生成');
    }
    getJWTSecret() {
        return this.config.jwt.secret;
    }
    getJWTConfig() {
        return this.config.jwt;
    }
    getAuthConfig() {
        return this.config.auth;
    }
    getServerConfig() {
        return this.config.server;
    }
    getSteamCMDConfig() {
        return this.config.steamcmd;
    }
    async updateSteamCMDConfig(updates) {
        this.logger.info('Updating SteamCMD config with:', updates);
        this.config.steamcmd = {
            ...this.config.steamcmd,
            ...updates
        };
        this.logger.info('New SteamCMD config is:', this.config.steamcmd);
        await this.saveConfig();
        this.logger.info('SteamCMD配置已更新');
    }
    getTerminalConfig() {
        return this.config.terminal;
    }
    async updateTerminalConfig(updates) {
        this.config.terminal = {
            ...this.config.terminal,
            ...updates
        };
        await this.saveConfig();
        this.logger.info('终端配置已更新');
    }
    getGameConfig() {
        return this.config.game;
    }
    async updateGameConfig(updates) {
        this.config.game = {
            ...this.config.game,
            ...updates
        };
        await this.saveConfig();
        this.logger.info('游戏配置已更新');
    }
    getSponsorConfig() {
        return this.config.sponsor;
    }
    async updateSponsorConfig(sponsorData) {
        this.config.sponsor = {
            ...sponsorData,
            validatedAt: new Date().toISOString()
        };
        await this.saveConfig();
        this.logger.info('赞助者密钥配置已更新');
    }
    async clearSponsorConfig() {
        delete this.config.sponsor;
        await this.saveConfig();
        this.logger.info('赞助者密钥配置已清除');
    }
    getDeveloperConfig() {
        return this.config.developer;
    }
    hasDeveloperPassword() {
        return !!(this.config.developer?.passwordHash && this.config.developer?.salt);
    }
    async setDeveloperPassword(passwordHash, salt) {
        this.config.developer = {
            passwordHash,
            salt
        };
        await this.saveConfig();
        this.logger.info('开发者密码已设置');
    }
    async clearDeveloperConfig() {
        delete this.config.developer;
        await this.saveConfig();
        this.logger.info('开发者配置已清除');
    }
    getSecurityConfig() {
        return this.config.security;
    }
    async updateSecurityConfig(updates) {
        this.config.security = {
            ...this.config.security,
            ...updates
        };
        await this.saveConfig();
        this.logger.info('安全配置已更新');
    }
    async updateJWTConfig(updates) {
        this.config.jwt = {
            ...this.config.jwt,
            ...updates
        };
        await this.saveConfig();
        this.logger.info('JWT配置已更新');
    }
    async checkAndResetTokenOnStartup() {
        const securityConfig = this.config.security;
        const isDevMode = process.env.DEV_MODE === 'true';
        if (isDevMode) {
            this.logger.info('开发模式下跳过JWT密钥重置，令牌将保持有效');
            return;
        }
        if (securityConfig.tokenResetRule === 'startup') {
            const startupFlagPath = path.join(path.dirname(this.configPath), '.last_startup');
            try {
                const lastStartup = await fs.readFile(startupFlagPath, 'utf-8');
                const lastStartupTime = new Date(lastStartup);
                const now = new Date();
                const timeDiff = now.getTime() - lastStartupTime.getTime();
                if (timeDiff > 60000) {
                    await this.regenerateJWTSecret();
                    this.logger.info('启动时重置JWT密钥（距离上次启动超过1分钟）');
                }
                else {
                    this.logger.info('启动时跳过JWT密钥重置（距离上次启动不足1分钟）');
                }
            }
            catch (error) {
                if (error.code === 'ENOENT') {
                    await this.regenerateJWTSecret();
                    this.logger.info('启动时重置JWT密钥（首次启动或启动标记文件不存在）');
                }
                else {
                    this.logger.error('检查启动标记文件失败:', error);
                }
            }
            try {
                await fs.writeFile(startupFlagPath, new Date().toISOString(), 'utf-8');
            }
            catch (error) {
                this.logger.error('更新启动标记文件失败:', error);
            }
        }
    }
}
