import { Context } from "koa";
import { ChannelHandler, LoginResult, PaymentResult } from "../interfaces/ChannelHandler";
import { ChannelConfig } from "../../config/channelConfig";
import axios from "axios";
import {PaymentHelper} from "../../utils/PaymentHelper";

const logger = require("../../utils/log");

/**
 * 三一iOS渠道处理器
 * 渠道ID: 12
 * 处理iOS平台的登录鉴权和支付回调
 */
export class SYIOSChannelHandler implements ChannelHandler {
    /**
     * 获取HTTPS代理配置
     * @returns HTTPS代理配置
     */
    private getHttpsAgent() {
        const https = require('https');
        return new https.Agent({
            rejectUnauthorized: false,
            secureProtocol: 'TLSv1_2_method',
            timeout: 10000
        });
    }

    /**
     * 获取通用请求头
     * @returns 请求头配置
     */
    private getCommonHeaders() {
        return {
            'User-Agent': 'Mozilla/5.0 (compatible; WebServer/1.0)',
            'Accept': 'application/json',
            'Content-Type': 'application/json'
        };
    }

    /**
     * iOS登录鉴权
     * @param ctx Koa上下文
     * @param config 渠道配置
     */
    async handleLogin(ctx: Context, config: ChannelConfig): Promise<LoginResult> {
        try {
            const { userToken } = ctx.request.body || ctx.request.query;
            
            // 验证必要参数
            if (!userToken) {
                logger.error("iOS登录鉴权失败 - 缺少userToken参数");
                return {
                    code: -1,
                    msg: "缺少必要参数: userToken",
                    data: null
                };
            }
            const gameid = config.paymentConfig?.gameId || '1550';
            logger.info("iOS登录鉴权请求参数:", { userToken, gameid });

            // 调用第三方鉴权API
            const apiUrl = `https://api.11h5.com/login?cmd=checkUserToken&userToken=${encodeURIComponent(userToken)}&gameid=${gameid}`;
            
            logger.info("调用iOS鉴权API:", { url: apiUrl });

            const response = await axios.get(apiUrl, {
                timeout: 10000,
                headers: this.getCommonHeaders(),
                httpsAgent: this.getHttpsAgent()
            });

            logger.info("iOS鉴权API响应:", response.data);

            // 根据错误码判断成功与否
            const responseData = response.data;
            
            if (responseData.error === 0) {
                // 成功：error = 0
                logger.info("iOS登录鉴权成功:", {
                    uid: responseData.uid,
                    nickname: responseData.nickname,
                    usertype: responseData.usertype
                });
                
                return {
                    code: 1,
                    msg: "登录成功",
                    data: {
                        uid: responseData.uid,
                        nickname: responseData.nickname,
                        headimgurl: responseData.headimgurl,
                        sex: responseData.sex,
                        focus: responseData.focus,
                        usertype: responseData.usertype
                    }
                };
            } else if (responseData.error === 401) {
                // 参数有误
                logger.error("iOS登录鉴权失败 - 参数有误:", responseData);
                return {
                    code: -1,
                    msg: "参数有误，请检查接口所需参数是否都已经填写正确",
                    data: null
                };
            } else if (responseData.error === 403) {
                // token验证失败
                logger.error("iOS登录鉴权失败 - token验证失败:", responseData);
                return {
                    code: -1,
                    msg: "token验证失败，同一个userToken只能验证一次，可通过刷新游戏重新获取",
                    data: null
                };
            } else {
                // 其他错误
                logger.error("iOS登录鉴权失败 - 未知错误:", responseData);
                return {
                    code: -1,
                    msg: "鉴权失败，请稍后重试",
                    data: null
                };
            }

        } catch (error) {
            logger.error("iOS登录鉴权出错:", error);
            return {
                code: -1,
                msg: "登录鉴权失败",
                data: null
            };
        }
    }

    /**
     * iOS支付回调处理
     * @param ctx Koa上下文
     * @param config 渠道配置
     */
    async handlePayment(ctx: Context, config: ChannelConfig): Promise<PaymentResult> {
        try {
            const data = ctx.request.query || ctx.request.body;
            logger.info("iOS支付回调参数:", data);

            // 验证必要参数（根据API文档）
            const requiredParams = ['openid', 'rmb', 'reqid', 'trans_id', 'product_id', 'notify_id', 'sign','txid'];
            for (const param of requiredParams) {
                if (!data[param]) {
                    logger.error(`iOS支付回调缺少必要参数: ${param}`);
                    return {
                        code: 0,
                        msg: `缺少必要参数: ${param}`
                    };
                }
            }

            // 验证签名（使用签名算法3）
            if (!this.verifyPaymentSignature(data, config)) {
                logger.error("iOS支付回调签名验证失败");
                return {
                    code: 0,
                    msg: "签名验证失败"
                };
            }

            // 提取notify_id进行订单校验
            const notify_id = data.notify_id;
            const gameid =  config.paymentConfig?.gameId || '1550';
            
            logger.info(`开始订单校验 - notify_id: ${notify_id}, gameid: ${gameid}`);

            // 调用订单校验
            const verifyResult = await this.verifyOrderInternal(gameid, notify_id, config);
            
            if (!verifyResult.success) {
                logger.error("订单校验失败:", verifyResult.message);
                return {
                    code: 0,
                    msg: `订单校验失败: ${verifyResult.message}`
                };
            }
            const orderId = data.txid;//订单号
            const out_trade_no = data.trans_id;//平台订单号
            const validation = await PaymentHelper.validateOrder(orderId);
            if (!validation.valid) {
                return {
                    code: validation.message?.includes("重复发货") ? 1 : 0,
                    msg: validation.message || "订单验证失败"
                };
            }
            const orderInfo = validation.orderInfo;

            logger.info("订单校验成功，开始处理支付发货逻辑");
            const result = await PaymentHelper.deliverOrder(
                orderInfo,
                ctx.request.ip,
                validation.url,
                out_trade_no
            );
            // 处理支付成功逻辑
            logger.info(`iOS支付成功 - 用户: ${data.openid}, 金额: ${data.rmb}, 订单: ${out_trade_no}, 发货结果:`, result);
            
            // 返回SUCCESS表示处理成功（根据API文档要求）
            ctx.body = "SUCCESS";
            
            return {
                code: 1,
                msg: "支付处理成功",
                data: {
                    openid: data.openid,
                    rmb: data.rmb,
                    reqid: data.reqid,
                    trans_id: data.trans_id,
                    product_id: data.product_id,
                    notify_id: data.notify_id,
                    userdata: data.userdata,
                    txid: data.txid,
                    product_count: data.product_count
                }
            };

        } catch (error) {
            logger.error("iOS支付回调处理出错:", error);
            return {
                code: 0,
                msg: "支付处理失败"
            };
        }
    }

    /**
     * 验证支付签名（签名算法3）
     * @param data 支付数据
     * @param config 渠道配置
     * @returns 验证结果
     */
    private verifyPaymentSignature(data: any, config: ChannelConfig): boolean {
        try {
            const privateKey = config.paymentConfig?.signKey || '';
            if (!privateKey) {
                logger.error("iOS支付签名验证失败 - 缺少私钥");
                return false;
            }

            // 1. 除去为空的参数
            const filteredParams: any = {};
            Object.keys(data).forEach(key => {
                if (key !== 'sign' && data[key] !== null && data[key] !== undefined && data[key] !== '') {
                    filteredParams[key] = data[key].toString();
                }
            });

            // 2. 对参数名按字母顺序排序
            const sortedKeys = Object.keys(filteredParams).sort();

            // 3. 构建待签名字符串
            const queryString = sortedKeys.map(key => {
                return `${key}=${filteredParams[key]}`;
            }).join('&');

            // 4. 拼接私钥
            const stringToSign = `${queryString}&key=${privateKey}`;

            // 5. 计算MD5签名并转大写
            const crypto = require('crypto');
            const expectedSignature = crypto.createHash('md5').update(stringToSign).digest('hex').toUpperCase();
            const actualSignature = data.sign;

            logger.info("iOS支付签名验证详情:", {
                filteredParams,
                queryString,
                stringToSign,
                expectedSignature,
                actualSignature,
                isValid: expectedSignature === actualSignature
            });

            return expectedSignature === actualSignature;
        } catch (error) {
            logger.error("iOS支付签名验证出错:", error);
            return false;
        }
    }

    /**
     * 生成支付签名（签名算法3）
     * @param params 签名参数
     * @param config 渠道配置
     * @returns 签名字符串
     */
    private generatePaymentSignature(params: any, config: ChannelConfig): string {
        try {
            const privateKey = config.paymentConfig?.signKey || '';
            if (!privateKey) {
                logger.error("iOS支付签名生成失败 - 缺少私钥");
                return "";
            }

            // 1. 除去为空的参数
            const filteredParams: any = {};
            Object.keys(params).forEach(key => {
                if (key !== 'sign' && params[key] !== null && params[key] !== undefined && params[key] !== '') {
                    filteredParams[key] = params[key].toString();
                }
            });

            // 2. 对参数名按字母顺序排序
            const sortedKeys = Object.keys(filteredParams).sort();

            // 3. 构建待签名字符串
            const queryString = sortedKeys.map(key => {
                return `${key}=${filteredParams[key]}`;
            }).join('&');

            // 4. 拼接私钥
            const stringToSign = `${queryString}&key=${privateKey}`;

            // 5. 计算MD5签名并转大写
            const crypto = require('crypto');
            const signature = crypto.createHash('md5').update(stringToSign).digest('hex').toUpperCase();

            logger.info("iOS支付签名生成详情:", {
                filteredParams,
                queryString,
                stringToSign,
                signature
            });

            return signature;
        } catch (error) {
            logger.error("iOS支付签名生成出错:", error);
            return "";
        }
    }

    /**
     * 内部订单校验方法（不依赖Koa上下文）
     * @param gameid 游戏ID
     * @param notify_id 平台通知ID
     * @param config 渠道配置
     */
    private async verifyOrderInternal(gameid: string, notify_id: string, config: ChannelConfig): Promise<{ success: boolean; message: string }> {
        try {
            // 生成订单校验签名
            const sign = this.generateOrderVerifySignature(gameid, notify_id, config);
            
            if (!sign) {
                logger.error("订单校验签名生成失败");
                return {
                    success: false,
                    message: "签名生成失败"
                };
            }

            logger.info("订单校验请求参数:", { gameid, notify_id, sign });

            // 调用第三方订单校验API
            const apiUrl = `https://login.11h5.com/pay/paygate/verify.php?gameid=${gameid}&notify_id=${encodeURIComponent(notify_id)}&sign=${encodeURIComponent(sign)}`;
            
            logger.info("调用订单校验API:", { url: apiUrl });

            const response = await axios.get(apiUrl, {
                timeout: 10000,
                headers: this.getCommonHeaders(),
                httpsAgent: this.getHttpsAgent()
            });

            logger.info("订单校验API响应:", response.data);

            // 检查响应结果
            const responseText = response.data.toString().trim();
            if (responseText === "SUCCESS") {
                logger.info("订单校验成功:", { notify_id, gameid });
                return {
                    success: true,
                    message: "订单校验成功"
                };
            } else {
                logger.warn("订单校验失败:", { notify_id, gameid, response: responseText });
                return {
                    success: false,
                    message: `订单校验失败: ${responseText}`
                };
            }

        } catch (error) {
            logger.error("订单校验出错:", error);
            return {
                success: false,
                message: "订单校验失败"
            };
        }
    }

    /**
     * 订单校验（公开接口）
     * @param ctx Koa上下文
     * @param config 渠道配置
     */
    async verifyOrder(ctx: Context, config: ChannelConfig): Promise<{ success: boolean; message: string }> {
        try {
            const { gameid, notify_id, sign } = ctx.request.query || ctx.request.body;
            
            // 验证必要参数
            if (!gameid) {
                logger.error("订单校验失败 - 缺少gameid参数");
                return {
                    success: false,
                    message: "缺少必要参数: gameid"
                };
            }

            if (!notify_id) {
                logger.error("订单校验失败 - 缺少notify_id参数");
                return {
                    success: false,
                    message: "缺少必要参数: notify_id"
                };
            }

            if (!sign) {
                logger.error("订单校验失败 - 缺少sign参数");
                return {
                    success: false,
                    message: "缺少必要参数: sign"
                };
            }

            logger.info("订单校验请求参数:", { gameid, notify_id, sign });

            // 验证签名
            const verifyData = { gameid, notify_id, sign };
            if (!this.verifyPaymentSignature(verifyData, config)) {
                logger.error("订单校验签名验证失败");
                return {
                    success: false,
                    message: "签名验证失败"
                };
            }

            // 调用第三方订单校验API
            const apiUrl = `https://login.11h5.com/pay/paygate/verify.php?gameid=${gameid}&notify_id=${encodeURIComponent(notify_id)}&sign=${encodeURIComponent(sign)}`;
            
            logger.info("调用订单校验API:", { url: apiUrl });

            const response = await axios.get(apiUrl, {
                timeout: 10000,
                headers: this.getCommonHeaders(),
                httpsAgent: this.getHttpsAgent()
            });

            logger.info("订单校验API响应:", response.data);

            // 检查响应结果
            const responseText = response.data.toString().trim();
            if (responseText === "SUCCESS") {
                logger.info("订单校验成功:", { notify_id, gameid });
                return {
                    success: true,
                    message: "订单校验成功"
                };
            } else {
                logger.warn("订单校验失败:", { notify_id, gameid, response: responseText });
                return {
                    success: false,
                    message: `订单校验失败: ${responseText}`
                };
            }

        } catch (error) {
            logger.error("订单校验出错:", error);
            return {
                success: false,
                message: "订单校验失败"
            };
        }
    }

    /**
     * 生成订单校验签名
     * @param gameid 游戏ID
     * @param notify_id 平台通知ID
     * @param config 渠道配置
     * @returns 签名字符串
     */
    private generateOrderVerifySignature(gameid: string, notify_id: string, config: ChannelConfig): string {
        try {
            const privateKey = config.paymentConfig?.signKey || '';
            if (!privateKey) {
                logger.error("订单校验签名生成失败 - 缺少私钥");
                return "";
            }

            // 构建参数对象
            const params = {
                gameid: gameid,
                notify_id: notify_id
            };

            // 使用签名算法3生成签名
            return this.generatePaymentSignature(params, config);
        } catch (error) {
            logger.error("订单校验签名生成出错:", error);
            return "";
        }
    }
}
