package com.engine.htsc.payment.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.engine.core.impl.Service;
import com.engine.htsc.payment.dao.BudgetDao;
import com.engine.htsc.payment.service.BxBudgetService;
import com.engine.htsc.payment.util.PayUtil;
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.RecordSetDataSource;
import weaver.general.Util;
import weaver.hrm.company.DepartmentComInfo;
import weaver.hrm.resource.ResourceComInfo;
import weaver.interfaces.htsc.comInfo.PropBean;
import weaver.interfaces.htsc.cus.HTUtil;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class BxBudgetServiceImpl extends Service implements BxBudgetService {
    private final Log log = LogFactory.getLog(PaymentServiceImpl.class);
    private final BudgetDao budgetDao = new BudgetDao();
    private final PropBean pp = new PropBean();


    @Override
    public String doBudgetAccount(String requestId, String tableName, String billStatus) throws Exception {
        log.info("====报销流程预算开始");
        log.info("====报销流程预算流程id@" + requestId + "@");
        log.info("====报销流程表名@" + tableName + "@");
        JSONObject params = new JSONObject();
        BudgetDao budgetDao = new BudgetDao();
        RecordSet rs = new RecordSet();
        ResourceComInfo rc = new ResourceComInfo();
        HTUtil htUtil = new HTUtil();
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        try {

            String budgetInvokeParam = budgetDao.mainBXFieldParam(tableName, requestId);
            rs.executeQuery(budgetInvokeParam);
//            String bz = "0"; //对应fkxx字段
            String lcbh = "";
            String requestname = "";
            String ngr = "";
            String mainId = "";
            if (rs.next()) {
                lcbh = Util.null2String(rs.getString("lcbh"));
                ngr = Util.null2String(rs.getString("ngr"));
                mainId = Util.null2String(rs.getString("id"));
//                bz = Util.null2String(rs.getString("fkxx"));
                requestname = Util.null2String(rs.getString("requestname"));
            }
//            String yskmTable = tableName + "_dt8"; //预算科目表，本币dt8，外币dt9
//            if ("1".equals(bz)) {
//                yskmTable = tableName + "_dt9";
//            }
            params.put("billnum", requestId);
            params.put("billname", lcbh);
            params.put("billstatus", billStatus);
            params.put("billtitle", requestname);
            params.put("personName", rc.getLastname(ngr));
            params.put("bizdate", df.format(LocalDateTime.now()));
            log.info(">>主表字段获取: @" + params + "@");
//            rs.executeQuery(budgetDao.isItPay(tableName, lcbh));
//            boolean isItFlag = false;
//            if (rs.next()) {
//                if ("1".equals(Util.null2String(rs.getString("FKLX")))) {
//                    isItFlag = true;
//                }
//            }
            JSONArray levelList = new JSONArray();
            String yskmTable = tableName + "_dt8";
            String bbYskmTableFieldParam = budgetDao.bxBBYskmTableFieldParam(yskmTable, mainId);
            rs.executeQuery(bbYskmTableFieldParam);
            int i = 1;
            while (rs.next()) {
                JSONObject level = new JSONObject();
//                String fycdbmfzr = Util.null2String(rs.getString("fycdbmfzr")); //费用承担部门负责人
                String fysjcdbm = Util.null2String(rs.getString("fysjcdbm")); //费用承担部门
                String yskm = Util.null2String(rs.getString("yskm")); //预算科目
                String JSHJJE = Util.null2String(rs.getString("jshjje"));
                String BHSJE = Util.null2String(rs.getString("bhsje"));
                String SJ = Util.null2String(rs.getString("sj"));
//                level.put("employeeNum", PayUtil.splitBmfzrThenJoin(fycdbmfzr, rc));
                level.put("deptNum", fysjcdbm);
                level.put("bgitem", PayUtil.superBudgetSubject(yskm)); //上级科目编码
                level.put("bgElement", "0101"); // 费用类型编码（默认传0101）
                level.put("billEntryID", UUID.randomUUID().toString() + "#" + i);
                level.put("itemEntryNum", yskm);
                level.put("amount", JSHJJE);
                level.put("notaxAmount", BHSJE); // 不含价税金额
                level.put("taxAmount", SJ); //税金
                //科目对应金额
                levelList.add(level);
                i++;
            }
            //外币
            String wbYskmTable = tableName + "_dt9";
            String wbYskmTableFieldParam = budgetDao.bxWBYskmTableFieldParam(wbYskmTable, mainId);
            rs.executeQuery(wbYskmTableFieldParam);
            while (rs.next()) {
                JSONObject level = new JSONObject();
//                String fycdbmfzr = Util.null2String(rs.getString("fycdbmfzr")); //费用承担部门负责人
                String fysjcdbm = Util.null2String(rs.getString("fysjcdbm")); //费用承担部门
                String yskm = Util.null2String(rs.getString("yskm")); //预算科目
                String rmbje = Util.null2String(rs.getString("rmbje"));
//                String BHSJE = Util.null2String(rs.getString("bhsje"));
//                String SJ = Util.null2String(rs.getString("sj"));
//                level.put("employeeNum", PayUtil.splitBmfzrThenJoin(fycdbmfzr, rc));
                level.put("deptNum", fysjcdbm);
                level.put("bgitem", PayUtil.superBudgetSubject(yskm)); //上级科目编码
                level.put("bgElement", "0101"); // 费用类型编码（默认传0101）
                level.put("billEntryID", UUID.randomUUID().toString() + "#" + i);
                level.put("itemEntryNum", yskm);
                level.put("amount", rmbje);
                level.put("notaxAmount", rmbje); // 不含价税金额
                level.put("taxAmount", 0); //税金
                //科目对应金额
                levelList.add(level);
                i++;
            }

            if (i == 1) {
                //没有明细
                log.info("预算科目明细为空");
                return "没有分摊的预算科目, 流程禁止提交";
            }
            params.put("list", levelList);
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put("data", params);
            log.info(">>预算接口调用参数 params : @" + params + "@");
            String resp = htUtil.budgetCommit(dataMap);
            log.info(">>预算接口调用返回 resp : @" + resp + "@");
            if (!"F1001".equals(resp)) {
                log.info("预算接口执行失败!返回值: " + resp);
                return "预算接口执行失败!返回值: " + resp;
            } else {
                boolean isUpdate = doBudgetMiddleTable(lcbh, billStatus,null, Arrays.asList(yskmTable, wbYskmTable), tableName);
                if (isUpdate) {
                    return "success";
                } else {
                    return "节点后附加操作更新预算中间表失败!";
                }
            }
        } catch (Exception e) {
            log.info("预算发生异常: " + e);
            throw new Exception(e);
        }
    }

    @Override
    public boolean doBudgetMiddleTable(String requestMark, String billStatus,String fbizdate, List<String> budgetKmTable, String mainTable) {
        log.info("报销流程,预算中间表更新\n  @requestMark=" + requestMark + ",billStatus=" + billStatus +
                ",budgetKmTable=" + JSONObject.toJSONString(budgetKmTable) + "@");
        if (StringUtils.isBlank(requestMark) || StringUtils.isBlank(billStatus) || CollectionUtils.isEmpty(budgetKmTable)) {
            log.info("更新失败,原因:流程编号或单据状态为空");
            return false;
        }
        try {
            //预算中间表外部数据源
            String budgetTableName = pp.getPropName("BudgetTableName");
            String nameIsExist = budgetDao.fNameIsExist(budgetTableName, requestMark);
            log.info("预算数据是否存在sql @" + nameIsExist + "@");
            RecordSetDataSource rsd = new RecordSetDataSource("BudgetRecords");
            rsd.execute(nameIsExist);
            if (rsd.next()) {
                String deleteAll = String.format("delete from %s where FNAME='%s'",
                        budgetTableName, requestMark);
                rsd.executeUpdateWithDatasource(deleteAll, "BudgetRecords");
                insertBudgetMiddleTable(requestMark, billStatus, fbizdate, budgetKmTable, mainTable, rsd);
//                updateBudgetMiddleTable(requestMark, billStatus, budgetKmTable, mainTable, rsd);
            } else {
                insertBudgetMiddleTable(requestMark, billStatus,fbizdate, budgetKmTable, mainTable, rsd);
            }
            return true;
        } catch (Exception e) {
            log.info("更新失败,原因: catch exception: " + e);
            return false;
        }
    }

    @Override
    public boolean dobugetModeUpdateYs(String requestId, String tableName) {
        return false;
    }

    @Override
    public boolean insertBudgetMiddleTable(String requestMark, String billStatus,String fbizDate, List<String> budgetKmTable, String mainTable, RecordSetDataSource rsd) throws Exception {
        log.info("预算信息不存在，执行更新方法 insertBudgetMiddleTable\n @requestMark=" + requestMark + ",billStatus=" + billStatus + "@");
        List<Object> mainInfo = null;
        List<List<Object>> budgetDtList  = new ArrayList<>();
        for(String buggetKmTable : budgetKmTable){
            Map<String, Object> budgetBody = getBudgetBody(requestMark, mainTable, buggetKmTable);
            mainInfo = (List<Object>) budgetBody.get("main");
            List<List<Object>> dtInfo = (List<List<Object>>)budgetBody.get("dt");
            budgetDtList.addAll(dtInfo);
        }
        //主表数据
        if (budgetDtList.size() == 0) {
            log.info("插入预算表中止,因为科目信息为空");
            return false;
        }
        DateTimeFormatter dfOnlyYear = DateTimeFormatter.ofPattern("yyyy"); //年
        DateTimeFormatter dfDateTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); //当前操作时间
        try {
            for (List<Object> singleValue : budgetDtList) {
                List<Object> insertValues = new ArrayList<>();
                insertValues.add(billStatus);
                insertValues.addAll(mainInfo);
                insertValues.add(dfOnlyYear.format(LocalDateTime.now()));
                if(StringUtils.isNotEmpty(fbizDate)){
                    insertValues.add(fbizDate);
                } else {
                    insertValues.add(dfDateTime.format(LocalDateTime.now()));
                }
                insertValues.addAll(singleValue);
                String budgetTableName = new PropBean().getPropName("BudgetTableName");
//				String budgetTableName = "T_BUD_BUDGETRECORDS";
                String insert = budgetDao.insertMiddleTable(budgetTableName);
                RecordSet recordSet = new RecordSet();
                recordSet.executeUpdateWithDatasource(insert, "BudgetRecords", insertValues);
            }
            return true;
        } catch (Exception e) {
            log.info("insertBudgetMiddleTable异常, [" + e + "]");
            return false;
        }
    }

    @Override
    public boolean updateBudgetMiddleTable(String requestMark, String billStatus, List<String> budgetKmTable, String mainTable, RecordSetDataSource rsd) throws Exception {
        log.info("预算信息已存在，执行更新方法 updateBudgetMiddleTable \n @requestMark=" + requestMark + ",billStatus=" + billStatus + "@");
        List<Object> mainInfo = null;
        List<List<Object>> budgetDtList  = new ArrayList<>();
        for(String buggetKmTable : budgetKmTable){
            Map<String, Object> budgetBody = getBudgetBody(requestMark, mainTable, buggetKmTable);
            mainInfo = (List<Object>) budgetBody.get("main");
            List<List<Object>> dtInfo = (List<List<Object>>)budgetBody.get("dt");
            budgetDtList.addAll(dtInfo);
        }
//        Map<String, Object> budgetBody = getBudgetBody(requestMark, mainTable, budgetKmTable);
//        List<Object> mainInfo = (List<Object>) budgetBody.get("main"); //主表数据
//        List<List<Object>> dtInfo = (List<List<Object>>) budgetBody.get("dt"); //预算数据
        if (budgetDtList.size() == 0) {
            log.info("插入预算表中止,因为科目信息为空");
            return false;
        }
        DateTimeFormatter dfOnlyYear = DateTimeFormatter.ofPattern("yyyy"); //年
        DateTimeFormatter dfDateTime = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); //当前操作时间
        RecordSet rs = new RecordSet();
        try {
            for (List<Object> singleValue : budgetDtList) {
                List<Object> insertValues = new ArrayList<>();
                insertValues.add(billStatus);
//				insertValues.add("0");
                insertValues.add(dfOnlyYear.format(LocalDateTime.now()));
                insertValues.add(dfDateTime.format(LocalDateTime.now()));
                insertValues.addAll(singleValue.subList(2,8));
                insertValues.add(singleValue.get(0));
                insertValues.add(mainInfo.get(0));
                String budgetTableName = new PropBean().getPropName("BudgetTableName");
//				String budgetTableName = "T_BUD_BUDGETRECORDS";
                String update = budgetDao.updateMiddleTable(budgetTableName);
                RecordSet recordSet = new RecordSet();
                recordSet.executeUpdateWithDatasource(update, "BudgetRecords", insertValues);
            }
            return true;
        } catch (Exception e) {
            log.info("insertBudgetMiddleTable异常, [" + e + "]");
            return false;
        }
    }


    /**
     * 获取插入表中的数据
     *
     * @param requestMark 流程编号
     * @return map
     */
    private Map<String, Object> getBudgetBody(String requestMark, String main, String budgetKmTable) throws Exception {
        Map<String, Object> res = new HashMap<>();
        log.info("付款流程表名: @" + main + "@");
        log.info("付款预算表名: @" + budgetKmTable + "@");
        RecordSet rs = new RecordSet();
        RecordSet rs1 = new RecordSet();
        DepartmentComInfo departmentComInfo = new DepartmentComInfo();
        String mainInfo = budgetDao.mainInfo(main, requestMark);
        rs.executeQuery(mainInfo);
        List<Object> mainValues = new ArrayList<>();
        String mainId = ""; //主副表关联id
        if (rs.next()) {
            mainValues.add(requestMark);
            mainValues.add(Util.null2String(rs.getString("REQUESTNAME"))); //流程编码
            mainValues.add(Util.null2String(rs.getString("LASTNAME"))); //拟稿人名称
//            mainValues.add(Util.null2String(rs.getString("DEPARTMENTCODE"))); //华泰部门code
            mainId = Util.null2String(rs.getString("ID"));
        }
        log.info("主表数据: @" + mainValues + "@");
        res.put("main", mainValues);
        String budgetKmTableInfo = budgetDao.budgetKmTableInfo(budgetKmTable, mainId, false);
        rs.executeQuery(budgetKmTableInfo);
        List<List<Object>> allDtValues = new ArrayList<>(); //所有明细科目数据 add dtValues 单行明细科目数据
        while (rs.next()) {
            List<Object> dtValues = new ArrayList<>(); //单行明细科目数据
            String yskm = Util.null2String(rs.getString("YSKM")); //科目
            String FYSJCDBM = Util.null2String(rs.getString("FYSJCDBM"));
            dtValues.add(yskm); //二级预算科目
            dtValues.add(PayUtil.superBudgetSubject(yskm)); //一级预算科目
            if (budgetKmTable.toLowerCase().contains("dt8")) {
                String JSHJJE = Util.null2String(rs.getString("JSHJJE"));
                String BHSJE = Util.null2String(rs.getString("BHSJE"));
                String SJ = Util.null2String(rs.getString("SJ"));
                String CYS = Util.null2String(rs.getString("CYS"));
                String PROJECTCODE = "";
                String XMMC = "";
                if ("".equals(JSHJJE)) {
                    dtValues.add(0.00); // 价税合计金额
                } else {
                    dtValues.add(Double.parseDouble(JSHJJE)); // 价税合计金额
                }
                if ("".equals(BHSJE)) {
                    dtValues.add(0.00); // 未税金额
                } else {
                    dtValues.add(Double.parseDouble(BHSJE)); // 未税金额
                }

                if ("".equals(SJ)) {
                    dtValues.add(0.00); //税金
                } else {
                    dtValues.add(Double.parseDouble(SJ)); //税金
                }
                dtValues.add(0.00); // 实际报销金额
                dtValues.add(0.00); // 差旅标准金额
                dtValues.add(PayUtil.overWeight(CYS)); // 是否超标
                String isItPay = "否";
                dtValues.add(isItPay);
                dtValues.add(PROJECTCODE); // it项目编码
                dtValues.add(XMMC); // it项目名称
            } else {
                String JSHJJE = Util.null2String(rs.getString("rmbje")); // 人民币金额
                String PROJECTCODE = "";
                String XMMC = "";
                if ("".equals(JSHJJE)) {
                    dtValues.add(0.00); // 价税合计金额
                    dtValues.add(0.00); // 未税金额
                } else {
                    dtValues.add(Double.parseDouble(JSHJJE)); // 价税合计金额
                    dtValues.add(Double.parseDouble(JSHJJE)); // 未税金额
                }
                String CYS = Util.null2String(rs.getString("CYS"));

                dtValues.add(0.00); //税金
                dtValues.add(0.00); // 实际报销金额
                dtValues.add(0.00); // 差旅标准金额
                dtValues.add(PayUtil.overWeight(CYS)); // 是否超标
                dtValues.add("否");
                dtValues.add(PROJECTCODE); // it项目编码
                dtValues.add(XMMC); // it项目名称
            }
            dtValues.add(departmentComInfo.getDepartmentCode(FYSJCDBM)); // 费用承担部门
            System.out.println("dtValues = " + dtValues);
            allDtValues.add(dtValues);
        }
        log.info("预算表数据" + budgetKmTable + "  @" + allDtValues + "@");
        res.put("dt", allDtValues);
        return res;
    }
}
