package weaver.interfaces.htsc.payment;

import com.alibaba.fastjson.JSONObject;
import com.engine.htsc.payment.pojo.PayWf;
import com.engine.htsc.payment.util.AssertUtil;
import com.engine.htsc.payment.util.CommonAPI;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import weaver.conn.RecordSet;
import weaver.conn.RecordSetTrans;
import weaver.general.GCONST;
import weaver.general.Util;
import weaver.hrm.company.DepartmentComInfo;
import weaver.interfaces.workflow.action.Action;
import weaver.soa.workflow.request.RequestInfo;
import weaver.workflow.request.RequestManager;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 付款流程
 * 拟稿提交后,审批链赋值
 * <p>
 * ①二级部门负责人
 * dt8或dt9,汇总 明细辅助二级部门负责人字段, 与 拟稿部门二级部门负责人 比较去重, 赋值到主表费用承担部门部门负责人（二级）
 * ②预算管理员
 * ③一级部门负责人
 */
public class PayCplAction implements Action {
  private final Log log = LogFactory.getLog(PayCplAction.class);

  @Override
  public String execute(RequestInfo requestInfo) {
    RequestManager requestManager = requestInfo.getRequestManager();
    String mt = requestManager.getBillTableName();
    String dt8 = mt + "_dt8";
    String dt9 = mt + "_dt9";
    int mainId = requestManager.getBillid(); //明细表id
    String reqId = requestInfo.getRequestid();

    //付款流程表单信息
    PayWf payWf = new PayWf(mt, dt8, dt9, mainId, reqId);
    log.info("====拟稿提交后触发审批链赋值逻辑@流程相关信息@" + payWf);

    RecordSet rs = new RecordSet();
    List<Object> updateParams = new ArrayList<>(); //更新主表数据参数
    boolean flag = false;
    try {
      boolean dt8HasData = checkDt(payWf, rs);
      //明细数据和主表数据比较逻辑
      Map<String, String> main = getMain(payWf, rs);
      List<String> ejbmfzrggfys = Arrays.asList(main.get("ejbmfzrggfys").split(","));
      List<String> ysglyggfys = Arrays.asList(main.get("ysglyggfys").split(","));
      List<String> bmfzrggfys = Arrays.asList(main.get("bmfzrggfys").split(","));
      List<String> eejbmfzrggfys = Arrays.asList(main.get("eejbmfzrggfys").split(","));
      String szbm = main.get("szbm");
      String sfxlxzcxshfcxf = main.get("sfxlxzcxshfcxf");
      log.info("====主表表数据@" + JSONObject.toJSONString(main));
      Map<String, List<String>> detail = getDetail(payWf, rs, dt8HasData, szbm);
      List<String> erbmfzr = detail.get("erbmfzr");
      List<String> ysgly = detail.get("ysgly");
      List<String> bmfzrL1 = detail.get("bmfzrL1");
      List<String> bmfzrL2 = detail.get("bmfzrL2");
      List<String> fykj = detail.get("fykj");
      log.info("====明细表数据@" + JSONObject.toJSONString(detail));

      //移除主表相同数据
      erbmfzr = removeAll(erbmfzr, ejbmfzrggfys);
      ysgly = removeAll(ysgly, ysglyggfys);
      bmfzrL1 = removeAll(bmfzrL1, bmfzrggfys);
      bmfzrL2 = removeAll(bmfzrL2, eejbmfzrggfys);

      //更新主表参数
      updateParams.add(erbmfzr.stream().distinct().filter(e -> !"".equals(e)).collect(Collectors.joining(",")));
      updateParams.add(ysgly.stream().distinct().filter(e -> !"".equals(e)).collect(Collectors.joining(",")));
      updateParams.add(bmfzrL1.stream().distinct().filter(e -> !"".equals(e)).collect(Collectors.joining(",")));
      updateParams.add(bmfzrL2.stream().distinct().filter(e -> !"".equals(e)).collect(Collectors.joining(",")));
      //费用会计
      String fykjList = fykj.stream().distinct().filter(i -> !"".equals(i)).collect(Collectors.joining(","));
      if ("24".equals(szbm)) {
        updateParams.add("23285");//拟稿部门为综合事务部，则给张激峰
      } else if (fykjList.contains(",")) {
        log.info("====费用会计存在多条记录@{},自动更新为左莹@" + fykjList);
//        #HTO-8842#废弃费用承担部门是否含有综合事务部OR营业部需求
//        if (accountFilterFlag(mainId, mt)) {
//          updateParams.add("23285"); //添加为张激峰
//        } else {
        updateParams.add("4649"); //添加为左莹
//        }
      } else {
        updateParams.add(fykjList);
      }
      if ("670".equals(szbm) && "0".equals(sfxlxzcxshfcxf)) {
        //所在部门为债券融资部 且 是否向联席主承销商... 为是
        flag = true;
      }

      log.info("====更新审批链字段值开始");
      log.info("====二级费用承担部门负责人@" + updateParams.get(0));
      log.info("====二级,一级部门预算管理员@" + updateParams.get(1));
      log.info("====一级费用承担部门负责人@" + updateParams.get(2));
      log.info("====二级费用承担部门上级负责人@" + updateParams.get(3));
      log.info("====承担部门费用会计@" + updateParams.get(4));

    } catch (Exception e) {
      log.error("====execute执行抛出异常@" + updateParams);
      e.printStackTrace();
    }

    //更新主表字段
    String updateWhere = "UPDATE " + payWf.getMt() + " set fycdbmfzrlcsp='" + updateParams.get(0) +
            "', ysgly='" + updateParams.get(1) + "', BMFZR='" + updateParams.get(2) + "'," +
            " EJBMFZRLCSP='" + updateParams.get(3) + "', fyhjshlcsp='" + updateParams.get(4) + "'";
    if (flag) {
      updateWhere += ",fgldlcsp=''";
    }
    updateWhere += " where REQUESTID=" + payWf.getReqId();

    log.info("====update语句@" + updateWhere);
    RecordSetTrans rst = new RecordSetTrans();
    try {
      rst.setAutoCommit(false);
      if (rst.executeUpdate(updateWhere)) {
        rst.commitOnly();
      } else {
        rst.rollbackOnly();
      }
      // HTO-10044
      refreshCommonSign(payWf);

      return SUCCESS;
    } catch (Exception e) {
      rst.rollback();
      log.error("====更新主表字段发生异常@" + e.getMessage());
      e.printStackTrace();
      requestInfo.getRequestManager().setMessageid("001");
      requestInfo.getRequestManager().setMessagecontent("审批链赋值异常,请联系管理员");
      return FAILURE_AND_CONTINUE;
    }

  }

  /**
   * 获取明细表数据
   * <p>
   * 1.明细辅助二级部门负责人
   * 2.预算管理员
   * 3.一级部门负责人
   *
   * @param payWf
   * @param rs
   * @return
   * @throws Exception
   */
  public Map<String, List<String>> getDetail(PayWf payWf, RecordSet rs, boolean dt8HasData, String szbm) throws Exception {
    Map<String, List<String>> result = new HashMap<>();
    DepartmentComInfo dc = new DepartmentComInfo();
    try {
      if (dt8HasData) {
        rs.executeQuery("select ID,FYCDBMJB,MXFZFYCDBMSP,MXFZDQBMFZR,MXFZEJBMFZR,YSGLY,FYHJ,FYSJCDBM from " + payWf.getDt8() + " where MAINID=" + payWf.getMainId());
      } else {
        rs.executeQuery("select ID,FYCDBMJB,MXFZFYCDBMSP,MXFZDQBMFZR,MXFZEJBMFZR,YSGLY,FYHJ,FYSJCDBM from " + payWf.getDt9() + " where MAINID=" + payWf.getMainId());
      }
      StringJoiner erbmfzr = new StringJoiner(",");
      StringJoiner ysgly = new StringJoiner(",");
      StringJoiner bmfzrL1 = new StringJoiner(",");
      StringJoiner bmfzrL2 = new StringJoiner(",");
      StringJoiner fykj = new StringJoiner(",");
      while (rs.next()) {
        String fysjcdbm = Util.null2String(rs.getString("FYSJCDBM"));
        String departmentCode = dc.getDepartmentCode(fysjcdbm);
        boolean isVisualDept = checkInMode(departmentCode);
        //所在部门 是 费用实际承担部门 相同时过滤
        //所在部门 是 虚拟部门 过滤
        //所在部门 是 团委(id=1000) 过滤, tw001
        if (!(szbm.equals(fysjcdbm) || isVisualDept || "tw001".equalsIgnoreCase(departmentCode))) {
          String jb = Util.null2String(rs.getString("FYCDBMJB")); // 级别,二级部门负责人时需要
          if ("1".equals(jb)) {
            //当费用承担部门为计财部(16)时,赋值空
            String mxfzdqbmfzr = Util.null2String(rs.getString("MXFZDQBMFZR"));
            if (!"16".equals(fysjcdbm)) {
              bmfzrL1.add(mxfzdqbmfzr); //明细辅助费用承担部门审批
            }
          } else if ("2".equals(jb)) {
            bmfzrL2.add(Util.null2String(rs.getString("MXFZEJBMFZR"))); //明细辅助费用承担部门审批
          } else {
            throw new Exception("部门级别取值为空,抛出异常");
          }
          erbmfzr.add(Util.null2String(rs.getString("MXFZFYCDBMSP"))); //明细辅助二级部门负责人
          ysgly.add(Util.null2String(rs.getString("YSGLY"))); //预算管理员
        }

        fykj.add(Util.null2String(rs.getString("FYHJ"))); //费用会计

      }
      result.put("erbmfzr", Arrays.asList(erbmfzr.toString().split(",")));
      result.put("ysgly", Arrays.asList(ysgly.toString().split(",")));
      result.put("bmfzrL1", Arrays.asList(bmfzrL1.toString().split(",")));
      result.put("bmfzrL2", Arrays.asList(bmfzrL2.toString().split(",")));
      result.put("fykj", Arrays.asList(fykj.toString().split(",")));
      return result;
    } catch (Exception e) {
      log.info("====获取明细表数据异常@" + e.getMessage());
      e.printStackTrace();
      throw new Exception(e);
    }
  }

  /**
   * 获取主表数据
   *
   * @param payWf
   * @param rs
   * @return
   * @throws Exception
   */
  public Map<String, String> getMain(PayWf payWf, RecordSet rs) throws Exception {
    String sql = "select ejbmfzrggfys,ysglyggfys,bmfzrggfys,eejbmfzrggfys,SZBM,sfxlxzcxshfcxf from " + payWf.getMt() + " where requestid=" + payWf.getReqId();
    Map<String, String> result = new HashMap<>();
    try {
      rs.executeQuery(sql);
      if (rs.next()) {
        result.put("ejbmfzrggfys", Util.null2String(rs.getString("ejbmfzrggfys"))); //二级部门负责人公共费用是
        result.put("eejbmfzrggfys", Util.null2String(rs.getString("eejbmfzrggfys")));
        result.put("ysglyggfys", Util.null2String(rs.getString("ysglyggfys"))); //预算管理员
        result.put("bmfzrggfys", Util.null2String(rs.getString("bmfzrggfys"))); //部门负责人
        result.put("szbm", Util.null2String(rs.getString("SZBM"))); //所在部门
        result.put("sfxlxzcxshfcxf", Util.null2String(rs.getString("sfxlxzcxshfcxf"))); //是否先付款后提供发票
      }
      return result;
    } catch (Exception e) {
      log.info("====获取主表数据异常@" + e.getMessage());
      e.printStackTrace();
      throw new Exception(e);
    }
  }

  /**
   * 判断明细表8或表9存在数据
   *
   * @param payWf
   * @param rs
   * @return true dt8存在数据 false dt9存在数据
   */
  public boolean checkDt(PayWf payWf, RecordSet rs) throws Exception {
    String sql = "select count(*) num from " + payWf.getDt9() + " where MAINID=" + payWf.getMainId();
    try {
      rs.executeQuery(sql);
      String num = "0";
      if (rs.next()) {
        num = Util.null2String(rs.getString("num"));
      }
      log.info("====判断明细8或明细9数据是否存在, true标识明细8存在数据@" + "0".equals(num));
      return "0".equals(num);
    } catch (Exception e) {
      log.error("====获取明细表数据异常@" + e.getMessage());
      e.printStackTrace();
      throw new Exception(e);
    }

  }

  /**
   * 去除重复的数据
   *
   * @param list1
   * @param list2
   * @return
   */
  public List<String> removeAll(List<String> list1, List<String> list2) {
    if (CollectionUtils.isEmpty(list1)) {
      return list1;
    }
    return list1.stream().filter(e -> !list2.contains(e)).collect(Collectors.toList());
  }

  /**
   * 查询是否存在于虚拟部门表
   *
   * @param dCode
   * @return
   */
  public boolean checkInMode(String dCode) {
    RecordSet rs = new RecordSet();
    String sql = "select DEPT_CODE from UF_FKXNBMPZB where DEPT_CODE='" + dCode + "'";
    rs.executeQuery(sql);
    return rs.next();
  }

  /**
   * 会计人员过滤
   *
   * @param mainId 明细表关联id
   * @return true, 综合事务部或者营业部; false,不包含
   */
  public boolean accountFilterFlag(int mainId, String tableName) {
    RecordSet rs = new RecordSet();
    rs.executeQuery("select FYSJCDBM from " + tableName + "_dt8 where MAINID=?", mainId);
    List<String> fybmList = new ArrayList<>();
    if (rs.getCounts() <= 0) {
      rs.executeQuery("select FYSJCDBM from " + tableName + "_dt9 where MAINID=?", mainId);
    }
    while (rs.next()) {
      fybmList.add(Util.null2String(rs.getString("FYSJCDBM")));
    }

    return fybmList
            .stream()
            .filter(StringUtils::isNotBlank)
            .anyMatch(bm -> "1091".equals(bm) || "24".equals(bm));

  }

  /**
   * HTO-10044
   * 会签 hqbmfzr
   */
  public String refreshCommonSign(PayWf payWf) {
    RecordSetTrans rst = new RecordSetTrans();
    rst.setAutoCommit(false);
    try {
      log.info("HTO-10044 会签部门负责人赋值处理");
      String sql = String.format("select ggfyqtfy,bmjb,fycdbmfzrlcsp,ejbmfzrlcsp,hqbmfzrxj,hqbmfzrzt,hqbmfzr,bmfzr from %s where requestid = %s",
              payWf.getMt(), payWf.getReqId());
      Map<String, String> row = CommonAPI.querySingleRow(sql);

      String ggfyqtfy = row.get("ggfyqtfy");
      if ("0".equals(ggfyqtfy)) {
        return "公共,其他费用ggfyqtfy=0";
      }
      String bmjb = row.get("bmjb");
      log.info("部门级别bmjb=1");
      List<String> bmfzr = convertList(row.get("bmfzr"));
      List<String> fycdbmfzrlcsp = convertList(row.get("fycdbmfzrlcsp"));
      List<String> ejbmfzrlcsp = convertList(row.get("ejbmfzrlcsp"));
      List<String> hqbmfzr = convertList(row.get("hqbmfzr"));

      //big sum 集合包含 部门负责人,费用承担部门负责人,二级部门负责人
      List<String> sum = new ArrayList<>();
      sum.addAll(bmfzr);
      sum.addAll(fycdbmfzrlcsp);
      sum.addAll(ejbmfzrlcsp);
      sum = sum.stream().filter(AssertUtil::isNotEmpty).collect(Collectors.toList());

      hqbmfzr.removeAll(sum);
      //update
      sql = String.format("update %s set hqbmfzr = '%s' where requestid=?", payWf.getMt(), String.join(",", hqbmfzr));
      if (rst.executeUpdate(sql,payWf.getReqId())) {
        rst.commitOnly();
      }

      if (sum.contains("26377") || sum.contains("23058")) {
        List<String> hqbmfzrxjList = convertList(row.get("hqbmfzrxj"));
        //26377(王玲),	23058(陈栋)
        //过滤信息技术部会签部门负责人
//        hqbmfzrxjList.removeAll(Arrays.asList("26377", "23058"));
        hqbmfzrxjList.removeAll(sum);
        //update
        sql = String.format("update %s set hqbmfzrxj = '%s' where requestid=?", payWf.getMt(), String.join(",", hqbmfzrxjList));
        if (rst.executeUpdate(sql,payWf.getReqId())) {
          rst.commitOnly();
        }
      }

      if (sum.contains("20010") || sum.contains("10971")) {
        List<String> hqbmfzrztList = convertList(row.get("hqbmfzrzt"));
        //20010(冯伟),10971(卢小群)
        //过滤资托会签部门负责人
//        hqbmfzrztList.removeAll(Arrays.asList("20010", "10971"));
        hqbmfzrztList.removeAll(sum);
        //update
        sql = String.format("update %s set hqbmfzrzt = '%s' where requestid=?", payWf.getMt(), String.join(",", hqbmfzrztList));
        if (rst.executeUpdate(sql,payWf.getReqId())) {
          rst.commitOnly();
        }
      }


    } catch (Exception e) {
      rst.rollback();
      return "refreshCommonSign 会签赋值异常";
    }

    return "refreshCommonSign 赋值成功";

  }

  public static void main(String[] args) {
    GCONST.setRootPath("");
    GCONST.setServerName("ecology");

    PayCplAction action = new PayCplAction();
    RequestManager requestManager = new RequestManager();
    requestManager.setBilltablename("formtable_main_171");
    requestManager.setBillid(1761);

    RequestInfo requestInfo = new RequestInfo();
    requestInfo.setRequestid("4804815");
    requestInfo.setRequestManager(requestManager);

    action.execute(requestInfo);
  }

  private List<String> convertList(String withDotStr) {
    return Arrays.stream(withDotStr.split(",")).collect(Collectors.toList());
  }

}
