import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import fs from 'fs/promises';
import path from 'path';
import { CaptchaManager } from './CaptchaManager.js';
export class AuthManager {
    constructor(configManager, logger) {
        this.users = new Map();
        this.loginAttempts = [];
        this.failedAttempts = new Map();
        this.configManager = configManager;
        this.logger = logger;
        this.usersFilePath = path.join(process.cwd(), 'data', 'users.json');
        this.attemptsFilePath = path.join(process.cwd(), 'data', 'login_attempts.json');
        this.captchaManager = new CaptchaManager(logger);
    }
    async initialize() {
        try {
            const dataDir = path.dirname(this.usersFilePath);
            await fs.mkdir(dataDir, { recursive: true });
            await this.captchaManager.initialize();
            await this.loadUsers();
            await this.loadLoginAttempts();
            this.logger.info('认证管理器初始化完成');
        }
        catch (error) {
            this.logger.error('认证管理器初始化失败:', error);
            throw error;
        }
    }
    async loadUsers() {
        try {
            const usersData = await fs.readFile(this.usersFilePath, 'utf-8');
            const users = JSON.parse(usersData);
            this.users.clear();
            users.forEach(user => {
                this.users.set(user.username, user);
            });
            this.logger.info(`加载了 ${users.length} 个用户`);
        }
        catch (error) {
            if (error.code === 'ENOENT') {
                this.logger.info('用户文件不存在，将创建新文件');
            }
            else {
                this.logger.error('加载用户文件失败:', error);
                throw error;
            }
        }
    }
    async loadLoginAttempts() {
        try {
            const attemptsData = await fs.readFile(this.attemptsFilePath, 'utf-8');
            this.loginAttempts = JSON.parse(attemptsData);
            const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000);
            this.loginAttempts = this.loginAttempts.filter(attempt => new Date(attempt.timestamp) > oneDayAgo);
            this.logger.info(`加载了 ${this.loginAttempts.length} 条登录尝试记录`);
        }
        catch (error) {
            if (error.code === 'ENOENT') {
                this.logger.info('登录尝试文件不存在，将创建新文件');
                this.loginAttempts = [];
            }
            else {
                this.logger.error('加载登录尝试文件失败:', error);
                throw error;
            }
        }
    }
    async saveUsers() {
        try {
            const users = Array.from(this.users.values());
            await fs.writeFile(this.usersFilePath, JSON.stringify(users, null, 2), 'utf-8');
        }
        catch (error) {
            this.logger.error('保存用户文件失败:', error);
            throw error;
        }
    }
    async saveLoginAttempts() {
        try {
            await fs.writeFile(this.attemptsFilePath, JSON.stringify(this.loginAttempts, null, 2), 'utf-8');
        }
        catch (error) {
            this.logger.error('保存登录尝试文件失败:', error);
            throw error;
        }
    }
    async createDefaultAdmin() {
        const defaultPassword = 'admin123';
        const hashedPassword = await bcrypt.hash(defaultPassword, 12);
        const adminUser = {
            id: 'admin',
            username: 'admin',
            password: hashedPassword,
            role: 'admin',
            createdAt: new Date().toISOString(),
            loginAttempts: 0
        };
        this.users.set('admin', adminUser);
        await this.saveUsers();
        this.logger.warn(`创建了默认管理员账户: admin / ${defaultPassword}`);
        this.logger.warn('请立即登录并修改默认密码！');
    }
    async login(username, password, ip, captchaId, captchaCode) {
        const user = this.users.get(username);
        const attempt = {
            username,
            ip,
            timestamp: new Date().toISOString(),
            success: false
        };
        const failedCount = this.failedAttempts.get(username) || 0;
        const requireCaptcha = failedCount >= 1;
        if (requireCaptcha) {
            if (!captchaId || !captchaCode) {
                return {
                    success: false,
                    message: '请输入验证码',
                    requireCaptcha: true
                };
            }
            if (!this.captchaManager.verifyCaptcha(captchaId, captchaCode)) {
                this.loginAttempts.push(attempt);
                await this.saveLoginAttempts();
                return {
                    success: false,
                    message: '验证码错误或已过期',
                    requireCaptcha: true
                };
            }
        }
        if (!user) {
            this.failedAttempts.set(username, failedCount + 1);
            this.loginAttempts.push(attempt);
            await this.saveLoginAttempts();
            return {
                success: false,
                message: '用户名或密码错误',
                requireCaptcha: this.failedAttempts.get(username) >= 1
            };
        }
        const isValidPassword = await bcrypt.compare(password, user.password);
        if (!isValidPassword) {
            this.failedAttempts.set(username, failedCount + 1);
            this.loginAttempts.push(attempt);
            await this.saveLoginAttempts();
            return {
                success: false,
                message: '用户名或密码错误',
                requireCaptcha: this.failedAttempts.get(username) >= 1
            };
        }
        this.failedAttempts.delete(username);
        user.lastLogin = new Date().toISOString();
        await this.saveUsers();
        attempt.success = true;
        this.loginAttempts.push(attempt);
        await this.saveLoginAttempts();
        const jwtConfig = this.configManager.getJWTConfig();
        const securityConfig = this.configManager.getSecurityConfig();
        let expiresIn;
        if (securityConfig.tokenExpireHours !== null) {
            expiresIn = `${securityConfig.tokenExpireHours}h`;
        }
        else {
            expiresIn = '876000h';
        }
        const signOptions = {};
        if (expiresIn) {
            signOptions.expiresIn = expiresIn;
        }
        const token = jwt.sign({
            userId: user.id,
            username: user.username,
            role: user.role
        }, jwtConfig.secret, signOptions);
        this.logger.info(`用户 ${username} 登录成功`);
        return {
            success: true,
            token,
            user: {
                id: user.id,
                username: user.username,
                role: user.role,
                createdAt: user.createdAt,
                lastLogin: user.lastLogin,
                loginAttempts: user.loginAttempts
            },
            message: '登录成功'
        };
    }
    verifyToken(token) {
        try {
            const jwtSecret = this.configManager.getJWTSecret();
            return jwt.verify(token, jwtSecret);
        }
        catch (error) {
            return null;
        }
    }
    async changePassword(username, oldPassword, newPassword) {
        const user = this.users.get(username);
        if (!user) {
            return {
                success: false,
                message: '用户不存在'
            };
        }
        const isValidOldPassword = await bcrypt.compare(oldPassword, user.password);
        if (!isValidOldPassword) {
            return {
                success: false,
                message: '原密码错误'
            };
        }
        const hashedNewPassword = await bcrypt.hash(newPassword, 12);
        user.password = hashedNewPassword;
        await this.saveUsers();
        this.logger.info(`用户 ${username} 修改密码成功`);
        return {
            success: true,
            message: '密码修改成功'
        };
    }
    async changeUsername(currentUsername, newUsername) {
        const user = this.users.get(currentUsername);
        if (!user) {
            return {
                success: false,
                message: '用户不存在'
            };
        }
        if (this.users.has(newUsername)) {
            return {
                success: false,
                message: '用户名已存在'
            };
        }
        if (!/^[a-zA-Z0-9]{3,30}$/.test(newUsername)) {
            return {
                success: false,
                message: '用户名只能包含字母和数字，长度为3-30个字符'
            };
        }
        user.username = newUsername;
        this.users.delete(currentUsername);
        this.users.set(newUsername, user);
        await this.saveUsers();
        this.logger.info(`用户 ${currentUsername} 修改用户名为 ${newUsername} 成功`);
        return {
            success: true,
            message: '用户名修改成功'
        };
    }
    getUsers() {
        return Array.from(this.users.values()).map(user => ({
            id: user.id,
            username: user.username,
            role: user.role,
            createdAt: user.createdAt,
            lastLogin: user.lastLogin,
            loginAttempts: user.loginAttempts,
            lockedUntil: user.lockedUntil
        }));
    }
    getLoginAttempts(limit = 100) {
        return this.loginAttempts
            .sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime())
            .slice(0, limit);
    }
    generateCaptcha() {
        return this.captchaManager.generateCaptcha();
    }
    checkIfRequireCaptcha(username) {
        const failedCount = this.failedAttempts.get(username) || 0;
        return failedCount >= 1;
    }
    hasUsers() {
        return this.users.size > 0;
    }
    async register(username, password, role = 'admin') {
        if (!/^[a-zA-Z0-9]{3,30}$/.test(username)) {
            return {
                success: false,
                message: '用户名只能包含字母和数字，长度为3-30个字符'
            };
        }
        if (password.length < 6) {
            return {
                success: false,
                message: '密码长度至少为6个字符'
            };
        }
        if (this.users.has(username)) {
            return {
                success: false,
                message: '用户名已存在'
            };
        }
        try {
            const hashedPassword = await bcrypt.hash(password, 12);
            const newUser = {
                id: username,
                username,
                password: hashedPassword,
                role,
                createdAt: new Date().toISOString(),
                loginAttempts: 0
            };
            this.users.set(username, newUser);
            await this.saveUsers();
            this.logger.info(`新用户注册成功: ${username} (${role})`);
            return {
                success: true,
                message: '注册成功',
                user: {
                    id: newUser.id,
                    username: newUser.username,
                    role: newUser.role,
                    createdAt: newUser.createdAt,
                    loginAttempts: newUser.loginAttempts
                }
            };
        }
        catch (error) {
            this.logger.error('用户注册失败:', error);
            return {
                success: false,
                message: '注册失败，请稍后重试'
            };
        }
    }
}
