import { logger } from "mslib"
import { IocConfigProvider, MemberConfig } from './Config';
import { ApiResponse } from './ApiResponse';
import { CryptoUtils } from './Security'; // 假设存在DES加密工具
let memberapi_config: MemberConfig = IocConfigProvider.getMemberConfig();

/**
 * 3DS加密服务装饰器（使用DES+时间戳实现）
 * 
 * 对方法返回结果进行DES加密处理，加密内容包含原始数据和时间戳
 * 将加密结果存入返回参数的ExtParam.token中
 * 
 * @param description 服务描述，仅为日志输出
 * @param config 配置选项
 * @param config.isLog 是否记录日志，默认true
 * @param config.isEncrypt 是否启用加密，默认true
 * @param config.expiresIn 过期时间(秒)，默认3600秒(1小时)
 */
export function Encrypt3DS(
    description?: string,
    config?: {
        isLog?: boolean,
        isEncrypt?: boolean,
        expiresIn?: number
    }
): MethodDecorator {
    // 设置默认配置
    const defaultConfig = {
        isLog: true,
        isEncrypt: true,
        expiresIn: 3600, // 默认过期时间1小时(3600秒)
        ...config
    };

    return function (target: Object, propertyKey: string, descriptor: PropertyDescriptor) {
        // 记录装饰器初始化信息
        let tapdId = IocConfigProvider.getBasicConfig()?.tapdId || '';
        logger.info(
            `${tapdId}.${target.constructor.name}/1.0`,
            `DES加密装饰器 - ${description || '未提供描述'}`
        );

        // 保存原始方法
        const originalMethod = descriptor.value;

        // 重写方法
        descriptor.value = async function (...args: any[]) {
            const tapdId = IocConfigProvider.getBasicConfig()?.tapdId || '';
            const serviceName = description || `${target.constructor.name}.${propertyKey}`;

            // 记录请求日志
            if (defaultConfig.isLog) {
                logger.info(
                    `tapd:${tapdId} DES加密服务 ${serviceName} 请求参数:${JSON.stringify(args)}`
                );
            }

            let result;
            try {
                // 调用原始方法获取结果
                result = await originalMethod.apply(this, args);

                // 如果需要加密且结果有效，则进行DES加密处理
                if (defaultConfig.isEncrypt && result && typeof result === 'object') {
                    // 确保有DES密钥
                    if (!memberapi_config.key) {
                        throw new Error('DES加密失败：未配置desSecret');
                    }
                    // 确保有DES密钥
                    if (!memberapi_config.iv) {
                        throw new Error('DES加密失败：未配置desSecret');
                    }

                    // 生成当前时间戳（秒级）
                    const timestamp = Math.floor(Date.now() / 1000);

                    // 构建包含原始数据和时间戳的加密对象
                    const dataToEncrypt = {
                        payload: result,
                        timestamp,
                        expiresIn: defaultConfig.expiresIn
                    };

                    // 使用DES加密
                    const token = CryptoUtils.desEncrypt(JSON.stringify(dataToEncrypt), memberapi_config.key, memberapi_config.iv);

                    // 确保ExtParam对象存在
                    if (!result.ExtParam) {
                        result.ExtParam = {};
                    }

                    // 将加密结果存入ExtParam.token字段
                    result.ExtParam.token = token;
                }
            } catch (error) {
                // 捕获并处理异常
                logger.error(
                    `tapd:${tapdId} DES加密服务 ${serviceName} 出现异常`,
                    error
                );
                // 返回统一的失败响应
                result = error instanceof Error
                    ? ApiResponse.successResult(1, `加密处理失败: ${error.message}`, '', `登录(MemberLogin) `)
                    : ApiResponse.successResult(1, `加密处理失败: ${String(error)}`, '', `登录(MemberLogin) `);
            }

            // 记录响应日志
            if (defaultConfig.isLog) {
                logger.info(
                    `tapd:${tapdId} DES加密服务 ${serviceName} 响应结果:${JSON.stringify(result)}`
                );
            }

            return result;
        };

        return descriptor;
    };
}
