package com.saye.hospitalgd.controller;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.saye.hospitalgd.commons.date.DateDUtil;
import com.saye.hospitalgd.commons.excel.ExportXLSX;
import com.saye.hospitalgd.commons.excel.HashMapConversionImpl;
import com.saye.hospitalgd.commons.excel.IConversionByExport;
import com.saye.hospitalgd.commons.log.ExceptionDUtil;
import com.saye.hospitalgd.commons.log.LogUtil;
import com.saye.hospitalgd.commons.string.StringDUtil;
import com.saye.hospitalgd.commons.uuid.UUIDGenerator;
import com.saye.hospitalgd.model.Dicinfo;
import com.saye.hospitalgd.model.StatusDefine;
import com.saye.hospitalgd.model.Users;
import com.saye.hospitalgd.scheduler.jobMethod.ReconciliationMethod;
import com.saye.hospitalgd.service.BankbillHistoryService;
import com.saye.hospitalgd.service.RefundService;
import com.saye.hospitalgd.service.TransactionDetailService;
import com.saye.hospitalgd.service.UnilateralService;
import com.saye.hospitalgd.service.system.DicinfoService;
import com.saye.hospitalgd.service.system.ServiceParamsService;
import com.saye.hospitalgd.util.IpUtil;
import com.saye.hospitalgd.util.RefundUtil;
import com.saye.hospitalgd.util.SeriesNumUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.*;

/**
 * @author thuang
 * @version 1.0
 * @description: 单边账
 * @date 2021/9/28 11:15
 */
@Controller
@RequestMapping("/unilateral")
@Api(tags = "单边账")
public class UnilateralController {

    @Autowired
    private UnilateralService unilateralService;

    @Autowired
    private TransactionDetailService transactionDetailService;

    @Autowired
    private DicinfoService dicinfoService;

    @Autowired
    private ServiceParamsService serviceParamsService;

    @Autowired
    private BankbillHistoryService bankbillHistoryService;

    @Autowired
    private RefundService refundService;

    @RequestMapping("/toUnilateral")
    public String toUnilateral(ModelMap modelMap) {

        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());

        calendar.add(Calendar.DATE, -1);
        Date startDate = calendar.getTime();

        String startTime = DateDUtil.DateToStr(DateDUtil.yyyy_MM_dd, startDate);
        String endTime = DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd);

        modelMap.addAttribute("startTime", startTime);
        modelMap.addAttribute("endTime", endTime);

        //支付方式
        List<Dicinfo> pay_type = dicinfoService.findDicinfoTreeNodeList("PAY_TYPE");
        modelMap.addAttribute("payTypeList", pay_type);

        //三方支付方式
        List<Dicinfo> third_pay = dicinfoService.findDicinfoTreeNodeList("THIRD_PAY");
        modelMap.addAttribute("thirdPayList", third_pay);


        return "financialReconciliation/unilateral";
    }


    /**
     * @description: 查询单边账记录
     * @author thuang
     * @date 2021/9/28 14:14
     * @version 1.0
     */
    @RequestMapping("/findAllUnilateral")
    @ResponseBody
    @ApiOperation("查询单边账记录")
    public HashMap<Object, Object> findAllUnilateral(String payType, String thirdPay, String startTime, String endTime, String err_type, int page, int limit) {
        HashMap<Object, Object> responseMap = new HashMap<>();

        try {
            HashMap<Object, Object> map = new HashMap<Object, Object>();
            map.put("payType", payType);
            map.put("thirdPay", thirdPay);
            map.put("startTime", startTime);
            map.put("endTime", endTime);
            map.put("err_type", err_type);

            PageHelper.startPage(page, limit);
            PageInfo<HashMap<Object, Object>> pageInfo = new PageInfo<HashMap<Object, Object>>(unilateralService.findAllUnilateral(map));

            responseMap.put("code", 0);
            responseMap.put("msg", "OK");
            responseMap.put("count", pageInfo.getTotal());
            responseMap.put("data", pageInfo.getList());
        } catch (Exception e) {
            e.printStackTrace();
            String msg = e.getMessage();
            responseMap.put("code", 1);
            responseMap.put("msg", "查询失败,原因：" + msg);
        }

        return responseMap;
    }

    /**
     * @description: 导出单边账明细
     * @author thuang
     * @date 2021/10/22 8:52
     * @version 1.0
     */
    @RequestMapping("/exportUnilateral")
    @ResponseBody
    @ApiOperation("导出单边账明细")
    public HashMap<Object, Object> exportUnilateral(@RequestBody HashMap<Object, Object> map) {
        HashMap<Object, Object> responseMap = new HashMap<Object, Object>();
        String errCode = "0";
        String errMsg = "";
        String dlName = "";
        String fileName = "";

        String dowloadName = StringDUtil.changeNullToEmpty(map.get("dowloadName"));

        try {

            List<HashMap<Object, Object>> list = unilateralService.findAllUnilateral(map);

            //支付方式
            List<Dicinfo> pay_type = dicinfoService.findDicinfoTreeNodeList("PAY_TYPE");
            HashMap<String, String> peyTypeMap = new HashMap<>();
            for (Dicinfo dicinfo : pay_type) {
                peyTypeMap.put(dicinfo.getDicvalue(), dicinfo.getDicname());
            }

            //三方支付方式
            List<Dicinfo> third_pay = dicinfoService.findDicinfoTreeNodeList("THIRD_PAY");
            HashMap<String, String> thirdPayMap = new HashMap<>();
            for (Dicinfo dicinfo : third_pay) {
                thirdPayMap.put(dicinfo.getDicvalue(), dicinfo.getDicname());
            }

            for (HashMap<Object, Object> hashMap : list) {
                //处理支付方式
                String paytype = StringDUtil.changeNullToEmpty(hashMap.get("PAYTYPE"));
                hashMap.put("PAYTYPE", peyTypeMap.get(paytype));

                String i_jyqd = StringDUtil.changeNullToEmpty(hashMap.get("I_JYQD"));
                hashMap.put("I_JYQD", thirdPayMap.get(i_jyqd));

                //处理错账类型
                String err_type = StringDUtil.changeNullToEmpty(hashMap.get("ERR_TYPE"));
                if ("1".equals(err_type)) {
                    hashMap.put("ERR_TYPE", "HIS单边账");
                } else if ("2".equals(err_type)) {
                    hashMap.put("ERR_TYPE", "三方单边账");
                } else if ("3".equals(err_type)) {
                    hashMap.put("ERR_TYPE", "差异账");
                } else if ("4".equals(err_type)) {
                    hashMap.put("ERR_TYPE", "跨天差异账");
                }

                String is_manager = StringDUtil.changeNullToEmpty(hashMap.get("IS_MANAGER"));
                if ("1".equals(is_manager)) {
                    hashMap.put("IS_MANAGER", "已处理");
                } else {
                    hashMap.put("IS_MANAGER", "未处理");
                }
            }

            if (list.size() > 0) {
                //定义标题头和文件名
                String[] DISTANCE_HEADERNAME = {"交易日期", "HIS金额", "支付方式", "三方金额", "支付方式", "错账类型", "平台交易号", "银商订单号", "操作员号", "交易时间", "是否已处理", "处理时间"};
                String[] sqlKey = {"TRADE_DATE", "AMOUNT", "PAYTYPE", "I_JYJE", "I_JYQD", "ERR_TYPE", "TRANID", "I_DDH", "HISOPERNUM", "TRADE_TIME", "IS_MANAGER", "MANAGER_TIME"};

                List<Object> rulList = new ArrayList<Object>(list);

                //创建工作表
                ExportXLSX exportXLS = new ExportXLSX(DISTANCE_HEADERNAME, sqlKey, ExportXLSX.A3, false);

                exportXLS.setTitleName(dowloadName);

                IConversionByExport conversion = new HashMapConversionImpl();
                exportXLS.setConversion(conversion);

                exportXLS.setData(rulList);

                exportXLS.modifyWidthOfHeader("5000", 0);
                exportXLS.modifyWidthOfHeader("5000", 1);
                exportXLS.modifyWidthOfHeader("5000", 2);
                exportXLS.modifyWidthOfHeader("5000", 3);
                exportXLS.modifyWidthOfHeader("5000", 4);
                exportXLS.modifyWidthOfHeader("5000", 5);
                exportXLS.modifyWidthOfHeader("10000", 6);
                exportXLS.modifyWidthOfHeader("10000", 7);
                exportXLS.modifyWidthOfHeader("5000", 8);
                exportXLS.modifyWidthOfHeader("5000", 9);
                exportXLS.modifyWidthOfHeader("5000", 10);
                exportXLS.modifyWidthOfHeader("5000", 11);

                // 文件名称
                //产生4位长度的随机码（由字母和数字组成）
                String randomStr = StringDUtil.generateRandomCodeForLength(4);
                dlName = DateDUtil.DateToStr(DateDUtil.yyyyMMddHHmmss, new Date()) + randomStr;
                fileName = dlName + ".xlsx";

                String uploadPath = StatusDefine.filePath + "/Unilateral/";
                File uploadPathFile = new File(uploadPath);
                if (!uploadPathFile.exists()) uploadPathFile.mkdirs();

                String savePath = uploadPath + fileName;
                exportXLS.execGenerateExcel(savePath);
            }

        } catch (Exception e) {
            errCode = "999";
            errMsg = "未知异常：" + ExceptionDUtil.getDetailExceptionMsg(e);
            LogUtil.error(this.getClass(), "@@@系统出错！【" + errMsg + "】");
        }

        responseMap.put("errCode", errCode);
        responseMap.put("errMsg", errMsg);
        responseMap.put("dlName", "Unilateral/" + fileName);
        return responseMap;
    }

    /**
     * @description: 处理单边账
     * @author thuang
     * @date 2021/11/29 15:01
     * @version 1.0
     */
    @PostMapping("/managerUnilateral")
    @ResponseBody
    @ApiOperation("处理单边账")
    public HashMap<Object, Object> managerUnilateral(HttpServletRequest request, @RequestBody HashMap<Object, Object> map) {
        HashMap<Object, Object> responseMap = new HashMap<>();
        String errCode = "0";
        String errMsg = "处理完成";
        Users user = (Users) SecurityUtils.getSubject().getPrincipal();
        String userId = user.getUserId();
        String userName = user.getUserName();
        String trueName = user.getTrueName();
        String ipAddr = IpUtil.getIpAddr(request);


        try {
            String id = StringDUtil.changeNullToEmpty(map.get("id"));
            String errType = StringDUtil.changeNullToEmpty(map.get("errType"));
            String managerType = StringDUtil.changeNullToEmpty(map.get("managerType"));
            String remark = StringDUtil.changeNullToEmpty(map.get("remark"));
            String payType = StringDUtil.changeNullToEmpty(map.get("payType"));
            String c_zffs = StringDUtil.changeNullToEmpty(map.get("c_zffs"));
            String trade_date = StringDUtil.changeNullToEmpty(map.get("trade_date"));
            String platformTransId = StringDUtil.changeNullToEmpty(map.get("platformTransId"));
            String c_ysddh = StringDUtil.changeNullToEmpty(map.get("c_ysddh"));

            //查询系统中设置的现金类型
            List<HashMap<Object, Object>> serviceParams = serviceParamsService.findParamValByParamCode("cash_code");
            String cash_code = StringDUtil.changeNullToEmpty(serviceParams.get(0).get("PARAM_VAL"));

            map.put("cash_code", cash_code);
            //判断 单边账情况和处理情况
            if ("1".equals(errType)) {
                //如果是his单边账
                //判断是否不计统计
                if ("2".equals(managerType)) {
                    //如果是2 不计统计 处理不计统计
                    map.put("is_active", "0");
                    transactionDetailService.updateJoinSetActiveByHis(map);

                    //重新计算对账结果记录表
                    ReconciliationMethod.managerReconciliation(transactionDetailService, new HashMap<Object, Object>() {{
                        put("trade_date", trade_date);
                    }});
                }
            } else if ("2".equals(errType)) {
                //如果是三方单边账
                //判断是否需要退账
                if ("1".equals(managerType)) {
                    //原路退回
                    if (cash_code.equals(payType)) {
                        //如果是现金 直接退出
                        throw new RuntimeException("现金帐无法直接退款");
                    }

                    //需要先记录退款操作 再调用退款接口 然后更新退款操作状态
                    //支付方式
                    //先在数据中查询这条记录
                    HashMap<Object, Object> searchMap = new HashMap<>();
                    searchMap.put("i_ddh", c_ysddh);
                    List<HashMap<Object, Object>> bankbillHistoryById = bankbillHistoryService.findBankbillHistoryById(searchMap);
                    HashMap<Object, Object> bankbillObj = bankbillHistoryById.get(0);
                    //全部走外联退费，不走九聚退费
//                    String bill_table_name = StringDUtil.changeNullToEmpty(bankbillHistoryById.get(0).get("bill_table_name"));

                    //先生成refundRequestId
                    String refundRequestId = "T" + DateDUtil.getCurrentDate(DateDUtil.yyyyMMddHHmmssSSS) + SeriesNumUtil.generateByRandom(3);
                    boolean isOk = true;

                    //调用掌医后台接口
                    List<HashMap<Object, Object>> palm_hospitalList = serviceParamsService.findParamValByParamCode("palm_hospital");
                    String palm_hospital = StringDUtil.changeNullToEmpty(palm_hospitalList.get(0).get("PARAM_VAL"));

                    // 九聚接口
//                    List<HashMap<Object, Object>> jfjk_wsdlList = serviceParamsService.findParamValByParamCode("jfjk_wsdl");
//                    String jfjk_wsdl = StringDUtil.changeNullToEmpty(jfjk_wsdlList.get(0).get("PARAM_VAL"));

                    try {

                        //根据excel表名名字选择退款方式
//                        if ("商户对账单".equals(bill_table_name)) {

                        HashMap<Object, Object> hashMap = new RefundUtil().refundPalmHospital(bankbillObj, palm_hospital, refundRequestId);
                        String errCode1 = StringDUtil.changeNullToEmpty(hashMap.get("errCode"));
                        //如果处理正常 保存返回信息
                        if ("0".equals(errCode1)) {
//                            hashMap.put("bill_table_name", bill_table_name);
                            hashMap.put("userName", userName);
                            hashMap.put("trueName", trueName);
                            hashMap.put("request_ip", ipAddr);
                            hashMap.put("c_ysddh", c_ysddh);
                            hashMap.put("id", UUIDGenerator.getUUID());

                            LogUtil.info(this.getClass(), trueName + "执行退款成功,内容" + hashMap.toString());

                            refundService.addRefundInfo(hashMap);
                        } else {
                            //如果不正常 返回错误信息 记录错误信息日志
                            errCode = errCode1;
                            errMsg = StringDUtil.changeNullToEmpty(hashMap.get("errMsg"));

                            LogUtil.error(this.getClass(), trueName + "执行退款失败，原因：" + errMsg);
                        }
//                        }
//                        else {
//
//                            //调用九聚接口
//                            HashMap<Object, Object> hashMap = new RefundUtil().refundThird(bankbillObj, jfjk_wsdl,refundRequestId);
//                            String errCode1 = StringDUtil.changeNullToEmpty(hashMap.get("errCode"));
//                            //如果处理正常 保存返回信息
//                            if ("0".equals(errCode1)) {
//                                hashMap.put("bill_table_name", bill_table_name);
//                                hashMap.put("userName", userName);
//                                hashMap.put("trueName", trueName);
//                                hashMap.put("request_ip", ipAddr);
//                                hashMap.put("c_ysddh", c_ysddh);
//                                hashMap.put("id", UUIDGenerator.getUUID());
//
//                                LogUtil.info(this.getClass(), trueName + "执行退款成功,内容" + hashMap.toString());
//
//                                refundService.addRefundInfo(hashMap);
//                            } else {
//                                //如果不正常 返回错误信息 记录错误信息日志
//                                errCode = errCode1;
//                                errMsg = StringDUtil.changeNullToEmpty(hashMap.get("errMsg"));
//
//                                LogUtil.error(this.getClass(), trueName + "执行退款失败，原因：" + errMsg);
//                            }
//                        }

                    } catch (Exception e) {
                        //连接直接断了等没有返回的情况
                        isOk = false;
                        e.printStackTrace();
                    }

                    //使用id查询扣款是否真的成功
                    if (!isOk) {
                        try {
                            //根据excel表名名字选择退款方式
//                            if ("商户对账单".equals(bill_table_name)) {
                            HashMap<Object, Object> hashMap = new RefundUtil().searchRefundPalmHospital(bankbillObj, palm_hospital, refundRequestId);
                            String errCode1 = StringDUtil.changeNullToEmpty(hashMap.get("errCode"));
                            //如果处理正常
                            if ("0".equals(errCode1)) {
                                // 分析其中数据
                                String queryResCode = StringDUtil.changeNullToEmpty(hashMap.get("queryResCode"));

                                if ("0".equals(queryResCode)) {
                                    //说明之前退款成功 记录数据
//                                    hashMap.put("bill_table_name", bill_table_name);
                                    hashMap.put("userName", userName);
                                    hashMap.put("trueName", trueName);
                                    hashMap.put("request_ip", ipAddr);
                                    hashMap.put("c_ysddh", c_ysddh);
                                    hashMap.put("id", UUIDGenerator.getUUID());

                                    LogUtil.info(this.getClass(), trueName + "执行退款成功,内容" + hashMap.toString());

                                    refundService.addRefundInfo(hashMap);

                                    //重新将errCode改为0
                                    errCode = "0";
//                                    }
//                                    else {
//                                        //说明之前退款失败 返回错误信息 不用记录
//                                        errCode = queryResCode;
//                                        String queryResInfo = StringDUtil.changeNullToEmpty(hashMap.get("queryResInfo"));
//                                        errMsg = queryResInfo;
//
//                                        LogUtil.error(this.getClass(), trueName + "执行退款失败，原因：" + errMsg);
//                                    }
                                } else {
                                    //查询都失败
                                    String errMsg1 = StringDUtil.changeNullToEmpty(hashMap.get("errMsg"));
                                    throw new RuntimeException("查询之前退款记录失败，原因：" + errMsg1);

                                }
                            }
//                            else {
//                                //调用九聚接口
//                                HashMap<Object, Object> hashMap = new RefundUtil().searchRefundThird(bankbillObj, jfjk_wsdl, refundRequestId);
//                                String errCode1 = StringDUtil.changeNullToEmpty(hashMap.get("errCode"));
//                                //如果处理正常
//                                if ("0".equals(errCode1)) {
//
//                                    // 分析其中数据
//                                    String queryResCode = StringDUtil.changeNullToEmpty(hashMap.get("queryResCode"));
//                                    if ("00".equals(queryResCode)) {
//                                        hashMap.put("bill_table_name", bill_table_name);
//                                        hashMap.put("userName", userName);
//                                        hashMap.put("trueName", trueName);
//                                        hashMap.put("request_ip", ipAddr);
//                                        hashMap.put("c_ysddh", c_ysddh);
//                                        hashMap.put("id", UUIDGenerator.getUUID());
//
//                                        LogUtil.info(this.getClass(), trueName + "执行退款成功,内容" + hashMap.toString());
//
//                                        refundService.addRefundInfo(hashMap);
//
//                                        //重新将errCode改为0
//                                        errCode = "0";
//                                    } else {
//                                        //如果不正常 返回错误信息 记录错误信息日志
//                                        errCode = queryResCode;
//                                        String queryResInfo = StringDUtil.changeNullToEmpty(hashMap.get("queryResInfo"));
//                                        errMsg = queryResInfo;
//                                        LogUtil.error(this.getClass(), trueName + "执行退款失败，原因：" + errMsg);
//                                    }
//                                } else {
//                                    //查询都失败
//                                    String errMsg1 = StringDUtil.changeNullToEmpty(hashMap.get("errMsg"));
//                                    throw new RuntimeException("查询九聚之前退款记录失败,原因：" + errMsg1);
//                                }
//                            }
                        } catch (Exception e) {
                            e.printStackTrace();
                            //连查询都错误  或者整个接口都没调通 那就先记录下生成的id以防之后要查
                            HashMap<Object, Object> hashMap = new HashMap<>();
//                            hashMap.put("bill_table_name", bill_table_name);
                            hashMap.put("userName", userName);
                            hashMap.put("trueName", trueName);
                            hashMap.put("request_ip", ipAddr);
                            hashMap.put("c_ysddh", c_ysddh);
                            hashMap.put("id", UUIDGenerator.getUUID());
                            hashMap.put("transactionAmount", "");
                            hashMap.put("refundInvoiceAmount", "查询扣款及扣款信息均失败");
                            hashMap.put("refundRequestId", refundRequestId);
                            hashMap.put("retrievalRefNum", "");
                            refundService.addRefundInfo(hashMap);
                        }
                    }
                } else if ("2".equals(managerType)) {
                    //不计统计
                    map.put("is_active", "0");
                    transactionDetailService.updateJoinSetActiveByThird(map);

                    //重新计算对账结果记录表
                    ReconciliationMethod.managerReconciliation(transactionDetailService, new HashMap<Object, Object>() {{
                        put("trade_date", trade_date);
                    }});
                }
            }

            //更新表状态为已处理 ，以及说明。
            if ("0".equals(errCode)) {
                map.put("manager_time", DateDUtil.getCurrentDate(DateDUtil.yyyy_MM_dd_HH_mm_ss));
                unilateralService.updateUnilateralManagerStatus(map);
            }
        } catch (Exception e) {
            //e.printStackTrace();
            errCode = "999";
            errMsg = "处理单边账失败,原因:" + e.getMessage();
            LogUtil.error(this.getClass(), userName + "[" + trueName + "]处理单边账失败，原因：" + e.getMessage());
        }

        responseMap.put("errCode", errCode);
        responseMap.put("errMsg", errMsg);
        return responseMap;
    }


}
