package com.kingdee.eas.custom.dormitorysystem.waterelectricity.handler;

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.framework.ejb.EJBFactory;
import com.kingdee.eas.custom.dormitorysystem.waterelectricity.WaterElectricityInfo;
import com.kingdee.eas.framework.CoreBillBaseInfo;
import com.kingdee.eas.hr.base.HRBillStateEnum;
import com.kingdee.eas.util.app.DbUtil;
import com.kingdee.jdbc.rowset.IRowSet;
import com.kingdee.shr.base.syssetting.api.bean.BatchMessageTipsBody;
import com.kingdee.shr.base.syssetting.api.bean.BatchMessageTipsHeader;
import com.kingdee.shr.base.syssetting.context.SHRContext;
import com.kingdee.shr.base.syssetting.exception.SHRWebException;
import com.kingdee.shr.base.syssetting.exception.ShrWebBizException;
import com.kingdee.shr.base.syssetting.json.GridDataEntity;
import com.kingdee.shr.perfweb.app.exception.SHRPerfWebBizException;
import com.kingdee.shr.perfweb.app.resource.SHRPerfWebResource;
import com.kingdee.shr.perfweb.util.SHRPerfWebResourceUtil;
import com.kingdee.shr.perfweb.web.handler.base.CommonBatchListHandler;
import com.kingdee.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ui.ModelMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;

/**
 * description: WaterElectricityBatchListHandler <br>
 * date: 2025/5/6 18:07 <br>
 * author: lhbj <br>
 * version: 1.0 <br>
 */
public abstract class WaterElectricityBatchListHandler extends CommonBatchListHandler {
    private static Logger logger = LoggerFactory.getLogger(WaterElectricityBatchListHandler.class);

    private String successMessage = "";

    public void setSuccessMessage(String successMessage) {
        this.successMessage = successMessage;
    }
    /**
     * 计算水电费用
     *
     * @param waterElectricityInfo
     * @param map
     * @param occupants
     * @return
     */
    protected CoreBillBaseInfo calculateWaterElectricity(CoreBillBaseInfo waterElectricityInfo, Map<String, Object> map,
                                                             Map<String, Object> occupants) {
        BigDecimal waterprice = (BigDecimal) waterElectricityInfo.get("waterprice");//水费单价
        BigDecimal electricityprice = (BigDecimal) waterElectricityInfo.get("electricityprice");//电费单价
        BigDecimal curMonthWater = (BigDecimal) map.get("curMonthWater");
        BigDecimal curMonthElecDegrees = (BigDecimal) map.get("curMonthElecDegrees");

        LocalDate startPeriodDate = (LocalDate) map.get("startPeriodDate");
        LocalDate endPeriodDate = (LocalDate) map.get("endPeriodDate");

        Date checkInDate = (Date) map.get("checkInDate");//入住日期

        Date checkOutDate = (Date) map.get("checkOutDate");//离宿日期

        waterElectricityInfo.put("waterTotalCost",(waterprice.multiply(curMonthWater)));
        waterElectricityInfo.put("electricityTotalCost",(electricityprice.multiply(curMonthElecDegrees)));
        //处理当月入住天数
        LocalDate checkInDateLocal = (new Date(checkInDate.getTime())).toInstant()
                .atZone(ZoneId.systemDefault()).toLocalDate();
        checkInDateLocal = (checkInDateLocal.compareTo(startPeriodDate) > 0 ? checkInDateLocal : startPeriodDate);

        LocalDate checkOutDateLocal = (new Date(checkOutDate.getTime())).toInstant()
                .atZone(ZoneId.systemDefault()).toLocalDate();
        checkOutDateLocal = (checkOutDateLocal.compareTo(endPeriodDate) < 0 ? checkOutDateLocal : endPeriodDate);

        long daysBetween = ChronoUnit.DAYS.between(checkInDateLocal, checkOutDateLocal);
        BigDecimal days = new BigDecimal((long) occupants.get("days"));
        waterElectricityInfo.put("allMonthDays",(days));
        waterElectricityInfo.put("monthDays",(new BigDecimal(daysBetween)));
        //?	当月水费：宿舍用水总费用/宿舍内所有人员当月总入住天数*该人员当前宿舍的入住天数；
        BigDecimal monthWaterAmount = waterElectricityInfo.getBigDecimal("waterTotalCost")
                .divide(days, BigDecimal.ROUND_HALF_UP, BigDecimal.ROUND_HALF_UP)
                .multiply(waterElectricityInfo.getBigDecimal("MonthDays"));
        waterElectricityInfo.put("monthWaterAmount",monthWaterAmount.setScale(2,BigDecimal.ROUND_HALF_UP));
        //?	当月电费：宿舍用电总费用/宿舍内所有人员当月总入住天数*该人员当前宿舍的入住天数；
        BigDecimal monthElectricityAmount = waterElectricityInfo.getBigDecimal("ElectricityTotalCost")
                .divide(days, BigDecimal.ROUND_HALF_UP, BigDecimal.ROUND_HALF_UP)
                .multiply(waterElectricityInfo.getBigDecimal("MonthDays"));
        waterElectricityInfo.put("monthElectricityAmount",monthElectricityAmount.setScale(2,BigDecimal.ROUND_HALF_UP));
        return waterElectricityInfo;
    }
    public static String convertListToString(Object[] array) {
        StringBuilder sb = new StringBuilder();
        int i = 0;

        for (int size = array.length; i < size; ++i) {
            if (size == 1) {
                sb.append((String) array[i]);
            } else if (i != size - 1) {
                sb.append((String) array[i]);
                sb.append(",");
            } else {
                sb.append((String) array[i]);
            }
        }
        return sb.toString();
    }
    protected void returnMessage(HttpServletRequest request, BatchMessageTipsHeader batchMessageTipsHeader, Map<String, Set<String>> result, Set<String> billids) {
        Set<String> sess = result.get("sess");
        Set<String> errs = result.get("errs");
        sess.addAll(errs);
        billids.removeAll(sess);
        request.setAttribute("billId", convertListToString(sess.toArray()));
        if (null != errs && (!errs.isEmpty())) {
            this.addBatchMessageTips(errs, "为锁定状态不能更新", batchMessageTipsHeader);
        }
        billids.removeAll(errs);
        if (null != billids && (!billids.isEmpty())) {
            this.addBatchMessageTips(errs, "为锁定状态不能更新", batchMessageTipsHeader);
        }
    }
    /**
     * 获取当前宿舍的总入住天数
     * 宿舍内所有人员当月总入住天数
     *
     * @param ctx
     * @param dormitorys
     * @param startPeriodDate
     * @param endPeriodDate
     * @return
     * @throws BOSException
     * @throws SQLException
     */
    protected Map<String, Map<String, Object>> getPersonOccupantsList(Context ctx,
                                                                      Collection<String> dormitorys, LocalDate startPeriodDate, LocalDate endPeriodDate
    ) throws BOSException, SQLException {

        //获取开始时间，结束时间
        String startPeriodDateStr = startPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
        String endPeriodDateStr = endPeriodDate.format(DateTimeFormatter.ISO_LOCAL_DATE);

        Map<String, Map<String, Object>> occupantsMap = Maps.newHashMap();
        //处理当月入住天数
        StringBuilder selCunt = new StringBuilder();
        selCunt.append(" select CFDormitoryID,CFPersonPositionID,CFCheckOutDate,CFCheckInDate from CT_OCC_Occupants ");
        selCunt.append(" where to_char(CFCheckOutDate ,'yyyy-MM-dd') >= '" + startPeriodDateStr + "' ");
        selCunt.append(" and to_char(CFCheckInDate ,'yyyy-MM-dd') <='" + endPeriodDateStr + "' ");
        selCunt.append(" and CFDormitoryID in('' ");
        for (String dormitory : dormitorys) {
            selCunt.append(",'");
            selCunt.append(dormitory);
            selCunt.append("'");
        }
        selCunt.append(" ) ");
        IRowSet rsCunt = DbUtil.executeQuery(ctx, selCunt.toString());

        while (rsCunt.next()) {
            String id = rsCunt.getString("CFDormitoryID");
            Map<String, Object> occupants = occupantsMap.get(id);
            if (null == occupants) {
                occupants = Maps.newHashMap();
                occupants.put("dormitoryID", id);
                occupants.put("days", 0L);
                occupantsMap.put(id, occupants);
            }

            LocalDate InDate = (new Date(rsCunt.getDate("CFCheckInDate").getTime())).toInstant()
                    .atZone(ZoneId.systemDefault()).toLocalDate();
            LocalDate OutDate = (new Date(rsCunt.getDate("CFCheckOutDate").getTime())).toInstant()
                    .atZone(ZoneId.systemDefault()).toLocalDate();
            InDate = (InDate.compareTo(startPeriodDate) > 0 ? InDate : startPeriodDate);
            OutDate = (OutDate.compareTo(endPeriodDate) < 0 ? OutDate : endPeriodDate);
            long daysBetween = ChronoUnit.DAYS.between(InDate, OutDate);
            long days = (long) occupants.get("days");
            occupants.put("days", days + daysBetween);
        }
        return occupantsMap;
    }
    /**
     * 锁定
     *
     * @param request
     * @param response
     * @param modelMap
     * @return
     * @throws SHRWebException
     */
    public void lockAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap, BatchMessageTipsHeader batchMessageTipsHeader) throws SHRWebException {
        String billId = this.getBillId(request);
        Context ctx = SHRContext.getInstance().getContext();
        try {
            StringBuilder sel = new StringBuilder();
            sel.append("select fid from CT_WOE_WaterElectricity where CFStutas='Lock'  ");
            if (!StringUtils.isEmpty(billId)) {
                String[] ids = billId.split(",");
                Set<String> errs = Sets.newHashSet();
                Set<String> sess = Sets.newHashSet();
                sess.addAll(Arrays.asList(ids));
                sel.append(" and fid in('' ");
                for (String id : ids) {
                    sel.append(",'");
                    sel.append(id);
                    sel.append("'");
                }
                sel.append(")");
                IRowSet rs = DbUtil.executeQuery(ctx, sel.toString());
                while (rs.next()) {
                    String id = rs.getString("fid");
                    errs.add(id);
                    this.addBatchMessageTip(id, "已经锁定，不能再次锁定。", batchMessageTipsHeader);
                }
                sess.removeAll(errs);
                for (String id : sess) {
                    try {
                        this.updateStutas(ctx, "enable", id);
                    } catch (SQLException throwables) {
                        throwables.printStackTrace();
                    }
                }
            }else {
                StringBuilder sel2 = new StringBuilder();
                sel2.append("select fid from CT_WOE_WaterElectricity where CFStutas!='Lock' ");
                Set<String> errs = Sets.newHashSet();
                Set<String> sess = Sets.newHashSet();
                IRowSet rs = DbUtil.executeQuery(ctx, sel2.toString());
                while (rs.next()) {
                    String id = rs.getString("fid");
                    this.updateStutas(ctx, "enable", id);
                    sess.add(id);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解锁
     *
     * @param request
     * @param response
     * @param modelMap
     * @return
     * @throws SHRWebException
     */
    public void unLockAction(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap, BatchMessageTipsHeader batchMessageTipsHeader) throws SHRWebException {
        String billId = this.getBillId(request);
        Context ctx = SHRContext.getInstance().getContext();
        try {
            StringBuilder sel = new StringBuilder();
            sel.append("select fid from CT_WOE_WaterElectricity where FBillState in (2,3,4) ");
            if (!StringUtils.isEmpty(billId)) {
                String[] ids = billId.split(",");
                Set<String> errs = Sets.newHashSet();
                Set<String> sess = Sets.newHashSet();
                sess.addAll(Arrays.asList(ids));
                sel.append(" and fid in('' ");
                for (String id : ids) {
                    sel.append(",'");
                    sel.append(id);
                    sel.append("'");
                }
                sel.append(")");
                IRowSet rs = DbUtil.executeQuery(ctx, sel.toString());
                while (rs.next()) {
                    String id = rs.getString("fid");
                    errs.add(id);
                    this.addBatchMessageTip(id, "薪资数据已经锁定，不能解锁。", batchMessageTipsHeader);
                }
                sess.removeAll(errs);
                for (String id : sess) {
                    try {
                        this.updateStutas(ctx, "disable", id);
                    } catch (SQLException throwables) {
                        throwables.printStackTrace();
                    }
                }
            }else {
                StringBuilder sel2 = new StringBuilder();
                sel2.append("select fid from CT_WOE_WaterElectricity where FBillState not in (2,3,4) ");
                Set<String> errs = Sets.newHashSet();
                Set<String> sess = Sets.newHashSet();
                IRowSet rs = DbUtil.executeQuery(ctx, sel2.toString());
                while (rs.next()) {
                    String id = rs.getString("fid");
                    this.updateStutas(ctx, "disable", id);
                    sess.add(id);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    protected String getBillId(HttpServletRequest request) throws SHRWebException {
        String billId = (String) request.getAttribute("billId");
        if (StringUtils.isEmpty(billId)) {
            billId = request.getParameter("billId");
        }

        if (StringUtils.isEmpty(billId)) {
            billId = request.getParameter("billID");
        }

        if (StringUtils.isEmpty(billId)) {
            return "";
        } else {
            return billId;
        }
    }





    public abstract String getTableName();

    public void updateStutas(Context ctx, String math, String uuid) throws SQLException {
        Connection conn = null;
        Statement state = null;

        try {
            conn = EJBFactory.getQueryConnection(ctx);
            state = conn.createStatement();
            if ("enable".equals(math)) {
                //锁定
                state.execute("update "+this.getTableName()+" set CFStutas='Lock' where fid='" + uuid + "'");

            } else if ("disable".equals(math)) {

                state.execute("update "+this.getTableName()+" set CFStutas='UnLock' where fid='" + uuid + "' and FBillState = 0 ");
            }
        } catch (SQLException var32) {
            var32.printStackTrace();
        } finally {
            if (state != null) {
                try {
                    state.close();
                } finally {
                    if (conn != null) {
                        conn.close();
                    }

                }
            }
        }
    }

    protected void handleEnableWithTips(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException {
        String SUCCESS_MESSAGE = SHRPerfWebResourceUtil.getRes(SHRPerfWebResource.OPERATESUCCESS, SHRContext.getInstance().getContext());
        BatchMessageTipsHeader batchMessageTipsHeader = new BatchMessageTipsHeader();
        String billId = null;
        try {
            int crossTotalCount = 0;
            int rows;
            int submitRecordsStep;

            this.callAction(request, response, modelMap, batchMessageTipsHeader);
            if (StringUtils.isEmpty(this.successMessage)) {
                this.successMessage = SUCCESS_MESSAGE;
            }
            billId = this.getBillId(request);
            Set<String> ids2 = new HashSet();
            if(!StringUtils.isEmpty(billId)) {
                ids2.addAll(Arrays.asList(billId.split(",")));
            }
            Set<String> errorIds = getErrorIdsByBatchMessageTip(batchMessageTipsHeader);
            ids2.removeAll(errorIds);
            addBatchMessageSuccessTips(ids2, this.successMessage, batchMessageTipsHeader);
            List<BatchMessageTipsBody> list = batchMessageTipsHeader.getResult();
            rows = list.size();
            Set<String> ids = new HashSet();
            for(BatchMessageTipsBody body : list){
                ids.add(body.getId());
            }
            batchMessageTipsHeader.setBillId(convertListToString(ids.toArray()));
            int failureCount = batchMessageTipsHeader.getFailureCount();
            submitRecordsStep = rows - failureCount;
            if (submitRecordsStep < 0) {
                submitRecordsStep = crossTotalCount - failureCount;
            }
            if (submitRecordsStep < 0) {
                submitRecordsStep = 0;
            }
            batchMessageTipsHeader.setSuccessCount(submitRecordsStep);
            this.writeSuccessData(batchMessageTipsHeader);
        } catch (IllegalAccessException var26) {
            logger.error("", var26);
            throw new ShrWebBizException(new SHRPerfWebBizException(SHRPerfWebBizException.SYSTEMERR));
        } catch (InvocationTargetException var27) {
            logger.error("", var27.getTargetException());
            throw new ShrWebBizException(var27.getCause().getMessage());
        } finally {
            this.setSuccessMessage(SUCCESS_MESSAGE);
        }
    }

    @Override
    protected void afterGetListData(HttpServletRequest request, HttpServletResponse response, GridDataEntity gridDataEntity) throws SHRWebException {
        super.afterGetListData(request, response, gridDataEntity);
        List<Map<String,Object>> rows = gridDataEntity.getRows();
        this.afterGetExportData(request,response,rows);
    }

    @Override
    public void afterGetExportData(HttpServletRequest request, HttpServletResponse response, List listData) throws SHRWebException {
        super.afterGetExportData(request, response, listData);
        List<Map<String,Object>> rows = listData;

        if(null!=rows&&!rows.isEmpty()){
            for(Map<String,Object> map : rows){
                HRBillStateEnum billState = (HRBillStateEnum) map.get("billState");
                map.put("billState",billState);
                map.put("billStateStr",HRBillStateExEnum.getEnum(billState.getValue()).toString());

            }
        }
    }

}
