package com.ruoyi.applet.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.ruoyi.applet.transfer.TransferToUser;
import com.ruoyi.model.domain.AppUsers;
import com.ruoyi.model.domain.AppletAmountLog;
import com.ruoyi.model.service.IAppUsersService;
import com.ruoyi.model.service.IAppletAmountLogService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.map.HashedMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Map;

@Slf4j
@Component
public class AppletAmountService {


    @Autowired
    private IAppUsersService appUsersService;
    
    @Autowired
    private IAppletAmountLogService appletAmountLogService;

    /*************************************************************************************/
    //微信小程序的 AppID
    @Value("${wechat-admin.appId}")
    private String appid;
    //商户号
    @Value("${wechat-admin.merchantId}")
    private String mchid;
    //商户API私钥路径
    @Value("${wechat.privateKeyPath}")
    private String privateKeyFilePath;
    //商户API公钥路径
    @Value("${wechat-admin.publicKeyPath}")
    private String wechatPayPublicKeyFilePath;
    //商户API公钥ID
    @Value("${wechat-admin.publicKeyId}")
    private String wechatPayPublicKeyId;
    //商户证书序列号
    @Value("${wechat-admin.merchantSerialNumber}")
    private String certiticateSerialNo;
    /*************************************************************************************/
    /**
     * 微信提现基础参数
     * @return
     */
    private Map getMap(){
        Map<String, Object> map = new HashedMap();//转账接口所需参数
        map.put("host", "https://api.mch.weixin.qq.com");//请求地址
        map.put("method", "POST");//请求类型
        map.put("path", "/v3/fund-app/mch-transfer/transfer-bills");//提现接口
        map.put("notifyUrl", "https://www.yurangongfang.com/massage-admin/massage/cash/cashoutNotify/");//回调接口

        //微信商户参数
        map.put("appid", appid);//小程序appid
        map.put("mchid", mchid);//商户号
        map.put("certiticateSerialNo", certiticateSerialNo);//商户序列号
        map.put("privateKeyFilePath", privateKeyFilePath);//商户私钥证书
        map.put("wechatPayPublicKeyId", wechatPayPublicKeyId);//商户公钥id
        map.put("wechatPayPublicKeyFilePath", wechatPayPublicKeyFilePath);//商户公钥证书

        map.put("transferSceneId", "1005");//商户转账场景ID 1005-佣金报酬
        map.put("transferRemark", "佣金报酬");//商户转账场景ID 1005-佣金报酬
        map.put("userRecvPerception", "劳务报酬");//商户转账场景ID 1005-佣金报酬

        map.put("infoType1","岗位类型");
        map.put("infoContent1","外卖员");
        map.put("infoType2","报酬说明");
        map.put("infoContent2","高温补贴");
        return map;
    }


    public TransferToUser.TransferToUserResponse cashOut(AppletAmountLog appletAmountLog){

        AppUsers user = appUsersService.selectAppUsersByUserId(appletAmountLog.getUserId());

        //1.微信提现基础参数
        Map map = getMap();
        //变化的用户信息参数
        map.put("openid", user.getOpenid());//用户openid(小程序)
        map.put("userName", appletAmountLog.getNameValue());//用户真实姓名
        map.put("transferAmount", appletAmountLog.getAmount());//提现金额, 单位为“分”
        String idStr = "H" + IdWorker.getIdStr();
        map.put("outBillNo", idStr);//商户单号

        TransferToUser client = new TransferToUser(
                map.get("mchid").toString(),  // 商户号，是由微信支付系统生成并分配给每个商户的唯一标识符，商户号获取方式参考 https://pay.weixin.qq.com/doc/v3/merchant/4013070756
                map.get("certiticateSerialNo").toString(), // 商户API证书序列号，如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013053053
                map.get("privateKeyFilePath").toString(), // 商户API证书私钥文件路径，本地文件路径
                map.get("wechatPayPublicKeyId").toString(), // 微信支付公钥ID，如何获取请参考 https://pay.weixin.qq.com/doc/v3/merchant/4013038816
                map.get("wechatPayPublicKeyFilePath").toString() // 微信支付公钥文件路径，本地文件路径
        );

        //2、场景信息
        TransferToUser.TransferToUserRequest request = new TransferToUser.TransferToUserRequest();
        request.appid = map.get("appid").toString();
        request.outBillNo = map.get("outBillNo").toString();
        request.transferSceneId = map.get("transferSceneId").toString();
        request.openid = map.get("openid").toString();
        request.userName = client.encrypt(map.get("userName").toString());
        request.transferAmount = appletAmountLog.getAmount().longValue()*100;//单位为分
        request.transferRemark = map.get("transferRemark").toString();
        request.notifyUrl = map.get("notifyUrl").toString();
        request.userRecvPerception = map.get("userRecvPerception").toString();
        request.transferSceneReportInfos = new ArrayList<>();
        {
            TransferToUser.TransferSceneReportInfo item0 = new TransferToUser.TransferSceneReportInfo();
            item0.infoType = map.get("infoType1").toString();
            item0.infoContent = map.get("infoContent1").toString();
            request.transferSceneReportInfos.add(item0);


            TransferToUser.TransferSceneReportInfo item1 = new TransferToUser.TransferSceneReportInfo();
            item1.infoType = map.get("infoType2").toString();
            item1.infoContent = map.get("infoContent2").toString();
            request.transferSceneReportInfos.add(item1);

        }

        String massage = "提现申请失败";

        //3、执行提现
        TransferToUser.TransferToUserResponse response = client.run(request, map);
        log.info("提现发起成功，outBillNo："+response.outBillNo + "，transferBillNo：" +response.transferBillNo + "，state：" +response.state+ "，packageInfo：" + response.packageInfo);
        switch (response.state){
            case ACCEPTED:
                log.info("转账已受理");
                massage = "转账已受理";
                break;
            case PROCESSING:
                log.info("转账锁定资金中。如果一直停留在该状态，建议检查账户余额是否足够，如余额不足，可充值后再原单重试");
                massage = "转账锁定资金中。如果一直停留在该状态，建议检查账户余额是否足够，如余额不足，可充值后再原单重试";
                break;
            case WAIT_USER_CONFIRM:
                log.info("待收款用户确认，可拉起微信收款确认页面进行收款确认");
                massage = "待收款用户确认，可拉起微信收款确认页面进行收款确认";
                break;
            case TRANSFERING:
                log.info("转账中，可拉起微信收款确认页面再次重试确认收款");
                massage = "转账中，可拉起微信收款确认页面再次重试确认收款";
                break;
            case SUCCESS:
                log.info("转账成功");
                massage = "转账成功";
                break;
            case FAIL:
                log.info("转账失败");
                massage = "转账失败";
                break;
            case CANCELING:
                log.info("商户撤销请求受理成功，该笔转账正在撤销中");
                massage = "商户撤销请求受理成功，该笔转账正在撤销中";
                break;
            case CANCELLED:
                log.info("转账撤销完成");
                massage = "转账撤销完成";
                break;
        }

        log.info("提现结果：" + massage);

        appletAmountLog.setPackageInfo(response.packageInfo);

        return response;
    }

    /**
     * 审核不通过，退还金额到用户账户
     * @param appletAmountLog 提现记录
     * @param auditRemark 审核备注
     * @return 处理结果
     */
    @Transactional
    public boolean auditReject(AppletAmountLog appletAmountLog, String auditRemark) {
        try {
            // 1. 检查记录状态
            if (appletAmountLog.getAuditStatus() != 0) {
                log.error("提现记录已经审核过了，ID: {}", appletAmountLog.getId());
                return false;
            }

            // 2. 查询用户信息
            AppUsers user = appUsersService.selectAppUsersByUserId(appletAmountLog.getUserId());
            if (user == null) {
                log.error("用户不存在，userId: {}", appletAmountLog.getUserId());
                return false;
            }

            // 3. 退还金额到用户账户（撤销提现时的扣减操作）
            BigDecimal refundAmount = appletAmountLog.getAmount();
            if (appletAmountLog.getMoneyType() == 0) {
                // 合伙人钱包 - 退还金额（提现时是减少，所以这里增加）
                user.setMoney(user.getMoney().add(refundAmount));
                log.info("合伙人钱包退还金额: {}, 用户ID: {}, 原余额: {}, 新余额: {}", 
                        refundAmount, user.getUserId(), user.getMoney().subtract(refundAmount), user.getMoney());
            } else if (appletAmountLog.getMoneyType() == 1) {
                // 伴宠师钱包 - 退还金额（提现时是减少，所以这里增加）
                user.setPrice(user.getPrice().add(refundAmount));
                log.info("伴宠师钱包退还金额: {}, 用户ID: {}, 原余额: {}, 新余额: {}", 
                        refundAmount, user.getUserId(), user.getPrice().subtract(refundAmount), user.getPrice());
            } else if (appletAmountLog.getMoneyType() == 2) {
                // 保证金 - 退还金额（提现时是增加，所以这里减少）
                user.setBaoPrice(user.getBaoPrice().subtract(refundAmount));
                log.info("保证金退还金额: {}, 用户ID: {}, 原余额: {}, 新余额: {}", 
                        refundAmount, user.getUserId(), user.getBaoPrice().add(refundAmount), user.getBaoPrice());
            }

            // 4. 更新用户余额
            appUsersService.updateAppUsers(user);

            // 5. 更新提现记录状态为审核不通过
            appletAmountLog.setAuditStatus(2); // 2-审核不通过
            appletAmountLog.setState(2); // 2-已退回
            appletAmountLog.setRemark(auditRemark); // 设置审核备注
            appletAmountLogService.updateById(appletAmountLog);

            // 6. 记录退款流水
            AppletAmountLog refundLog = new AppletAmountLog();
            refundLog.setUserId(user.getUserId());
            
            if (appletAmountLog.getMoneyType() == 0) {
                refundLog.setTitle("合伙人钱包提现审核不通过退款");
            } else if (appletAmountLog.getMoneyType() == 1) {
                refundLog.setTitle("伴宠师钱包提现审核不通过退款");
            } else if (appletAmountLog.getMoneyType() == 2) {
                refundLog.setTitle("保证金提现审核不通过退款");
            }
            
            refundLog.setAmount(refundAmount);
            refundLog.setType(0); // 0-收入（退款）
            refundLog.setState(1); // 1-成功
            refundLog.setCreateTime(LocalDateTime.now());
            refundLog.setMoneyType(appletAmountLog.getMoneyType());
            refundLog.setNameValue(appletAmountLog.getNameValue());
            refundLog.setAuditStatus(1); // 1-审核通过（退款记录自动通过）
            
            appletAmountLogService.save(refundLog);

            log.info("审核不通过处理完成，退还金额: {}, 用户ID: {}, 审核备注: {}", 
                    refundAmount, user.getUserId(), auditRemark);
            
            return true;
        } catch (Exception e) {
            log.error("审核不通过处理失败，用户ID: {}, 金额: {}", appletAmountLog.getUserId(), appletAmountLog.getAmount(), e);
            return false;
        }
    }

    /**
     * 审核通过，更新提现记录状态并执行微信提现
     * @param appletAmountLog 提现记录
     * @param auditRemark 审核备注
     * @return 处理结果
     */
    @Transactional
    public boolean auditApprove(AppletAmountLog appletAmountLog, String auditRemark) {
        try {
            // 1. 检查记录状态
            if (appletAmountLog.getAuditStatus() != 0) {
                log.error("提现记录已经审核过了，ID: {}", appletAmountLog.getId());
                return false;
            }

            // 2. 更新提现记录状态为审核通过
            appletAmountLog.setAuditStatus(1); // 1-审核通过
            appletAmountLog.setState(0); // 0-处理中
            appletAmountLog.setRemark(auditRemark); // 设置审核备注
            appletAmountLogService.updateById(appletAmountLog);

            // 3. 执行实际的微信提现操作
            try {
                TransferToUser.TransferToUserResponse response = this.cashOut(appletAmountLog);
                
                // 4. 根据微信提现结果更新状态
                if (response != null) {
                    switch (response.state) {
                        case SUCCESS:
                            appletAmountLog.setState(1); // 1-成功
                            log.info("提现审核通过并执行成功，用户ID: {}, 金额: {}", appletAmountLog.getUserId(), appletAmountLog.getAmount());
                            break;
                        case ACCEPTED:
                        case PROCESSING:
                        case WAIT_USER_CONFIRM:
                        case TRANSFERING:
                            appletAmountLog.setState(0); // 0-处理中
                            log.info("提现审核通过，微信提现处理中，用户ID: {}, 金额: {}, 状态: {}", 
                                    appletAmountLog.getUserId(), appletAmountLog.getAmount(), response.state);
                            break;
                        case FAIL:
                            appletAmountLog.setState(2); // 2-失败
                            log.error("提现审核通过但微信提现失败，用户ID: {}, 金额: {}", appletAmountLog.getUserId(), appletAmountLog.getAmount());
                            break;
                        default:
                            appletAmountLog.setState(0); // 0-处理中
                            break;
                    }
                    
                    // 更新packageInfo
                    if (response.packageInfo != null) {
                        appletAmountLog.setPackageInfo(response.packageInfo);
                    }
                } else {
                    appletAmountLog.setState(2); // 2-失败
                    log.error("提现审核通过但微信提现返回空结果，用户ID: {}, 金额: {}", appletAmountLog.getUserId(), appletAmountLog.getAmount());
                }
            } catch (Exception e) {
                log.error("微信提现执行异常，用户ID: {}, 金额: {}", appletAmountLog.getUserId(), appletAmountLog.getAmount(), e);
                appletAmountLog.setState(2); // 2-失败
            }
            
            appletAmountLogService.updateById(appletAmountLog);

            log.info("审核通过处理完成，用户ID: {}, 金额: {}, 审核备注: {}", 
                    appletAmountLog.getUserId(), appletAmountLog.getAmount(), auditRemark);
            
            return true;
        } catch (Exception e) {
            log.error("审核通过处理失败，用户ID: {}, 金额: {}", appletAmountLog.getUserId(), appletAmountLog.getAmount(), e);
            return false;
        }
    }

}
