package com.bcxin.ins.weixin.order.service.impl;

import com.alibaba.fastjson.JSON;
import com.bcxin.ins.rest.UserSupportUtil;
import com.bcxin.ins.core.entity.PageResult;
import com.bcxin.ins.core.entity.R;
import com.bcxin.ins.core.util.DOM;
import com.bcxin.ins.entity.policy_core.InsInsuranceSlip;
import com.bcxin.ins.entity.policy_core.InsMailPolicy;
import com.bcxin.ins.entity.policy_core.InsRoleInpolicy;
import com.bcxin.ins.entity.policy_core.InsTransaction;
import com.bcxin.ins.entity.policy_special.SpecialExhibition;
import com.bcxin.ins.entity.product_core.ProPrimary;
import com.bcxin.ins.service.order.InsInsuranceSlipAPIService;
import com.bcxin.ins.service.order.InsRoleInpolicyAPIService;
import com.bcxin.ins.service.order.InsTransactionAPIService;
import com.bcxin.ins.service.order.PolicyService;
import com.bcxin.ins.util.IdWorker;
import com.bcxin.ins.util.RegionUtils;
import com.bcxin.ins.vo.ClientUserVo;
import com.bcxin.ins.vo.ConstProp;
import com.bcxin.ins.vo.DictConst;
import com.bcxin.ins.vo.LOTEPolicyVo;
import com.bcxin.ins.weixin.order.dao.WeiXinOrderMapper;
import com.bcxin.ins.weixin.order.service.*;


import com.bcxin.ins.weixin.product.service.InsMailPolicyService1;
import com.bcxin.ins.weixin.product.service.impl.WeiXinProductServiceImpl;
import com.bcxin.mybatisplus.mapper.EntityWrapper;
import com.bcxin.mybatisplus.toolkit.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Service
@Transactional
public class WeiXinOrderServiceImpl implements WeiXinOrderService {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private WeiXinOrderMapper weiXinOrderMapper;
    @Autowired
    private InsRoleInpolicyAPIService insRoleInpolicyService;
    @Autowired
    private InsMailPolicyService1 insMailPolicyService;
    @Autowired
    private InsInsuranceSlipAPIService insInsuranceSlipService;
    @Autowired
    private SpecialExhibitionService1 specialExhibitionService1;
    @Autowired
    private WeiXinProductServiceImpl weiXinProductService;
    @Autowired
    private InsTransactionAPIService insTransactionAPIService;
    @Autowired
    private PolicyService policyService;

    @Override
    public PageResult query(Map<Object, Object> p) {
        return new PageResult(weiXinOrderMapper.queryCnt(p), weiXinOrderMapper.query(p));
    }

    /**
     * <b> 展责险调用接口获取电子保单 </b>
     * @author ZXF
     * @create 2018/04/12 0012 11:01
     * @version
     * @注意事项 </b>
     */
    @Override
    public Map<Object,Object> queryDZBDBySlipID(Map<Object, Object> p) {
        logger.info(JSON.toJSONString(p));
        //如果参数中没有订单ID，就从session拿，如果还没有，就返回空
        Map<Object,Object> m = new HashMap<Object,Object>();
        String ret = ConstProp.CODE_FAILURE,msg = ConstProp.BLANK_CHAR;
        if (p.get("ins_insurance_slip_id") == null || "".equals(String.valueOf(p.get("ins_insurance_slip_id")))){
            msg = "数据丢失，请刷新后重试";
        }else{
            String path = policyService.HTTP_PAC_ZZX_DZBD(Long.parseLong(String.valueOf(p.get("ins_insurance_slip_id"))));
            if(StringUtils.isNotEmpty(path)){
                m.put("path",path);
                ret = ConstProp.CODE_SUCCESS;msg = "获取成功";
            }else{
                msg = "电子保单获取失败";
            }
        }
        m.put("ret",ret);
        m.put("msg",msg);
        return m;
    }

    /** 根据订单ID 查询出系列的投保数据 */
    @Override
    public Map<Object,Object> queryDetailVoBySlipID(Map<Object, Object> p , HttpServletRequest req){
        logger.info(JSON.toJSONString(p));
        //如果参数中没有订单ID，就从session拿，如果还没有，就返回空
        if(p.get("ins_insurance_slip_id")==null || "".equals(String.valueOf(p.get("ins_insurance_slip_id")))) return null;
        Map  m=  weiXinOrderMapper.queryDetailVoBySlipID(p);
        if(m==null) return null;
        Map a = (Map)m.get("applicant");
        Map i = (Map)m.get("special");
        Map imp = (Map)m.get("ins_mail_policy");
        if(a!=null && StringUtils.isNotEmpty( String.valueOf(a.get("reg_district"))))
            m.put("area", RegionUtils.getRegionNameByALLCode(String.valueOf(a.get("reg_province")),String.valueOf(a.get("reg_city")), String.valueOf(a.get("reg_district"))));
//            m.put("area", comRegionAPIService.getRegionName(String.valueOf(a.get("reg_province")),String.valueOf(a.get("reg_city")), String.valueOf(a.get("reg_district"))));
        if(i!=null && StringUtils.isNotEmpty(String.valueOf(i.get("ex_county"))))
            m.put("ex_area", RegionUtils.getRegionNameByALLCode(String.valueOf(i.get("ex_province")), String.valueOf(i.get("ex_city")), String.valueOf(i.get("ex_county"))));
//            m.put("ex_area", comRegionAPIService.getRegionName(String.valueOf(i.get("ex_province")), String.valueOf(i.get("ex_city")), String.valueOf(i.get("ex_county"))));
        if(imp!=null && StringUtils.isNotEmpty(String.valueOf(imp.get("bank_city"))))
            imp.put("bank_area", RegionUtils.getRegionNameByALLCode(String.valueOf(imp.get("bank_province")), String.valueOf(imp.get("bank_city")), null));
//            imp.put("bank_area", comRegionAPIService.getRegionName(String.valueOf(imp.get("bank_province")), String.valueOf(imp.get("bank_city")),""));
        //获得多个支付信息transactionList
        m.put("transactionList",insTransactionAPIService.selectList(new EntityWrapper<InsTransaction>().addFilter(" insurance_slip_id = {0} ",p.get("ins_insurance_slip_id"))));
        return m;
    }

    /** 投保人信息保存 */
    public R applicant(Map<Object, Object> p  ,HttpServletRequest req) {
        try {
            InsInsuranceSlip iis = null;
            Map<Object,Object> pp = weiXinProductService.queryByProductID(p); //获得产品的一系列的详细数据
            String pCode = String.valueOf(pp.get("product_code"));
            if(p.get("ins_insurance_slip_id")==null || "".equals(String.valueOf(p.get("ins_insurance_slip_id")).trim())){//如果传入id那么就是插入，并且初始化关联表数据
                IdWorker idWorker =  new IdWorker(31, 0);
                //邮寄地址
                InsMailPolicy insMailPolicy = new InsMailPolicy();
//                insMailPolicy.setNeed_receipt(0);
//                insMailPolicy.setNeed_insur_bill(0);
                insMailPolicy.setIns_mail_policy_id(idWorker.nextId());

                //扩展字段表
                SpecialExhibition specialExhibition = new SpecialExhibition();
                specialExhibition.setSpecial_exhibition_id(idWorker.nextId());

                //订单
                iis = new InsInsuranceSlip();
                iis.setIns_insurance_slip_id(idWorker.nextId());
                iis.setMailPolicy(insMailPolicy);
                iis.setSpecial_id(specialExhibition.getSpecial_exhibition_id());
                iis.setStart_time(new Date());
                iis.setSigned_date(new Date());
                iis.setTrade_serial_number(String.valueOf(idWorker.nextId()));//设置订单的编号
                iis.setOrder_status(DictConst.ORDER_STATUS_TBZ);//订单状态变为投保中
                ProPrimary prom = DOM.mtd(p, new ProPrimary());
                iis.setPro_primary( prom ); //产品主表的实体，为了保存pro_primary_id
                if(req.getSession().getAttribute("recommendCode")!=null) iis.setRecommend_code(String.valueOf(req.getSession().getAttribute("recommendCode")));//保存业务支撑用户ID作为分销索引
                iis.setRegister_user_id(Long.valueOf(String.valueOf(p.get("system_params_user_id")))); //注册用户ID，就是登录用户的ID

                //产品ID获得保费
//                Map<Object,Object> pp = weiXinProductService.queryByProductID(p); //获得产品的一系列的详细数据
                iis.setPremium(new BigDecimal(String.valueOf(pp.get("fixed_premium")))); //设置保费
//                String pCode = String.valueOf(pp.get("product_code"));
                if(StringUtils.isEmpty(pCode) ? false : pCode.indexOf("ZZX-PAC")>-1){
                    iis.setInsured_amount(policyService.setInsuredAmountByProductId(prom.getPro_primary_id()));
                }
                //投保人
                InsRoleInpolicy insRoleInpolicy1 = new InsRoleInpolicy();
                insRoleInpolicy1.setInsurance_slip(iis);
                insRoleInpolicy1.setKind("1");

                //被保险人
                InsRoleInpolicy insRoleInpolicy2 = new InsRoleInpolicy();
                insRoleInpolicy2.setInsurance_slip(iis);
                insRoleInpolicy2.setKind("2");

                insInsuranceSlipService.insert(iis);  //插入订单表数据
                insRoleInpolicyService.insert(insRoleInpolicy1);  //插入投保人
                insRoleInpolicyService.insert(insRoleInpolicy2); //插入被保险人
                insMailPolicyService.insert(insMailPolicy); //插入邮寄地址信息
                specialExhibitionService1.insert(specialExhibition); //插入扩展字段表
            }else{
                iis=  DOM.mtd(p, new InsInsuranceSlip());
            }

            //投保人信息保存，包含订单id TODO Applicant
            InsRoleInpolicy iri =  DOM.mtd(p, new InsRoleInpolicy());
            iri.setInsurance_slip(iis); //订单对象，传入订单ID
            iri.setKind("1"); //1是投保人（只能有一个），2是被保险人（多）
            List<InsRoleInpolicy> l  = insRoleInpolicyService.selectList(new EntityWrapper<InsRoleInpolicy>().addFilter(
                    " kind=1 and insurance_slip_id={0}",iis.getIns_insurance_slip_id()));
            if(l.size()==0)  throw new Exception("数据异常，订单未正确初始化");
            if(l.size()!=1)  throw new Exception("存在多个投保人");//存在就修改
            iri.setIns_role_inpolicy_id(l.get(0).getIns_role_inpolicy_id());
            if(!insRoleInpolicyService.updateById(iri))  throw new Exception("保存失败");//存在就修改

            if("2".equals(iri.getId_type())||"6".equals(iri.getId_type())){
                //如果证件类型为税务登记证或统一信用码就存session，用于之后流程中的发票中的税务号录入
                req.getSession().setAttribute("zj_code", iri.getOrganization_code());
            }

            return new R(true, String.valueOf(iis.getIns_insurance_slip_id()));
        } catch (Exception e) {
            logger.error("团意险订单更新过程事务发现异常，回滚数据",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new R(false, "事务发现异常，"+e.getMessage());
        }
    }

    /** 被保险人信息保存 */
    @Override
    public R saveInsurant(Map<Object, Object> p, HttpServletRequest req) {
        try {
            //除了第一个可以不传订单ID，其他页面必须要有订单记录存在，否则报错
            if(weiXinOrderMapper.queryDetailVoBySlipID(p)==null)  throw new Exception("订单不存在");

            InsInsuranceSlip iis=  DOM.mtd(p, new InsInsuranceSlip());
            InsRoleInpolicy iri =  DOM.mtd(p, new InsRoleInpolicy());
            iri.setInsurance_slip(iis); //订单对象，传入订单ID
            iri.setKind("2"); //1是投保人（只能有一个），2是被保险人（多）
            //被投保人信息保存，包含订单id
            //查询kind=2 并且 订单id为传入的订单id的被保险人 是否存在
            List<InsRoleInpolicy> l = insRoleInpolicyService.selectList(new EntityWrapper<InsRoleInpolicy>().addFilter(
                    " kind=2 and insurance_slip_id={0}",iis.getIns_insurance_slip_id()));
            if(l.size()==0)  throw new Exception("数据异常，订单未正确初始化");
            if(l.size()!=1)  throw new Exception("存在多个被保险人");//存在就修改
            iri.setIns_role_inpolicy_id(l.get(0).getIns_role_inpolicy_id());
            if(!insRoleInpolicyService.updateById(iri))  throw new Exception("保存失败"); //存在就修改 layer.open({content:"操作失败",btn: '我知道了'});

            return new R(true,  String.valueOf(iis.getIns_insurance_slip_id()));
        } catch (Exception e) {
            logger.error("团意险订单更新过程事务发现异常，回滚数据",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new R(false, "事务发现异常，"+e.getMessage());
        }
    }

    /** 扩展字段信息保存 */
    @Override
    public R saveSpecial(Map<Object, Object> p, HttpServletRequest req) {
        try {
            //除了第一个可以不传订单ID，其他页面必须要有订单记录存在，否则报错
            if(weiXinOrderMapper.queryDetailVoBySlipID(p)==null)  throw new Exception("订单不存在");

            //扩展字段表
            SpecialExhibition  se = DOM.mtd(p, new SpecialExhibition());
            if(ConstProp.DIGIT_ZERO.equals(se.getContains())){
                se.setBuild_com_name(" ");
                se.setSubcontracting_units(" ");
            }
            se.setExhibitor_name(StringUtils.isEmpty(se.getExhibitor_name())? " " : se.getExhibitor_name());
            se.setExhibitor_type(StringUtils.isEmpty(se.getExhibitor_type())? " " : se.getExhibitor_type());
            se.setExhibitor_code(StringUtils.isEmpty(se.getExhibitor_code())? " " : se.getExhibitor_code());
            if(!specialExhibitionService1.updateById(se)) throw new Exception("保存失败");

            //订单表关联上扩展字段表
            InsInsuranceSlip iis=  DOM.mtd(p, new InsInsuranceSlip());
            iis.setMailPolicy(null); //不更新邮寄地址
            iis.setInception_date(se.getStar_time()); //保障 生效日期
            iis.setPlanned_end_date(se.getEnd_time()); //保障 失效日期
            //展责险计算保费
            String result = policyService.zzx_amount_count(String.valueOf(p.get("product_code")),se.getEx_acreage());
            if(ConstProp.CODE_SUCCESS.equals(result.split(ConstProp.POUND_SIGN)[0])){
                iis.setPremium(new BigDecimal(result.split(ConstProp.POUND_SIGN)[1]));
            }
            if(!insInsuranceSlipService.updateById(iis)) throw new Exception("保存失败");

            return new R(true,  String.valueOf(iis.getIns_insurance_slip_id()));
        } catch (Exception e) {
            logger.error("团意险订单更新过程事务发现异常，回滚数据",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new R(false, "事务发现异常，"+e.getMessage());
        }
    }

    /** 发票 纸质保单*/
    @Override
    public R insMailPolicy(Map<Object, Object> p, HttpServletRequest req) {
        try {
            //除了第一个可以不传订单ID，其他页面必须要有订单记录存在，否则报错
            if(weiXinOrderMapper.queryDetailVoBySlipID(p)==null)  throw new Exception("订单不存在");

            InsMailPolicy  imp =  DOM.mtd(p, new InsMailPolicy());
            if(!insMailPolicyService.updateById(imp)) throw new Exception("保存失败");

            InsInsuranceSlip iis=  DOM.mtd(p, new InsInsuranceSlip());
            return new R(true,  String.valueOf(iis.getIns_insurance_slip_id()));
        } catch (Exception e) {
            logger.error("团意险订单更新过程事务发现异常，回滚数据",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new R(false, "事务发现异常，"+e.getMessage());
        }
    }

    /**
     * 展责险初始化或更新订单数据
     * @param vo
     * @param recommendCode
     * @return
     */
    @Override
    public R pendingLOTEPolicyVoPolicy(LOTEPolicyVo vo, String recommendCode){
        try {
            ClientUserVo userdetail = UserSupportUtil.getSessionUser();
            if (  userdetail == null ) {
                return new R(false, "账户已过期，请登录后操作");
            }
            if(StringUtils.isEmpty(vo.getOid())){
                String orderID = ConstProp.BLANK_CHAR;
                if(StringUtils.isNotEmpty(vo.getProduct_id())){
                    orderID = policyService.createOrderAndGetOrderIDByProductID(Long.parseLong(vo.getProduct_id()),Long.parseLong(userdetail.getOid()),recommendCode,"");
                }
                if(StringUtils.isNotEmpty(orderID)){
                    vo.setOid(orderID);
                }else{
                    return new R(false, "订单初始化创建失败，请刷新页面后重试！");
                }
            }
            Map<String, Object> map = policyService.obtainLOTEPolicyVoSetUp(vo);
            if(map != null){
                return new R(true,  String.valueOf(map.get(ConstProp.ORDER_ID)));
            }else{
                return new R(false, "数据丢失，请刷新页面后重试！");
            }
        }catch (Exception e){
            logger.error("展责险订单更新过程事务发现异常，回滚数据",e);
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return new R(false, "订单更新过程出现异常！");
        }
    }

    /**
     * 查询展责险订单信息
     * @param order_id
     * @return
     */
    @Override
    public LOTEPolicyVo accordingToOrderIDToGetLOTEPolicyVo(Long order_id){
        return policyService.accordingToOrderIDToGetLOTEPolicyVo(order_id);
    }

}


