package com.engine.salary.remote.attend.service.impl;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSONObject;
import com.engine.core.impl.Service;
import com.engine.kq.cmd.report.GetKQReportCmd;
import com.engine.salary.remote.attend.cmd.GetSearchListCmd;
import com.engine.salary.remote.attend.entity.Attend4Salary;
import com.engine.salary.remote.attend.service.RemoteAttend4SalaryService;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.valid.ValidUtil;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import weaver.general.BaseBean;
import weaver.general.Util;

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

@Slf4j
public class RemoteAttend4SalaryServiceImpl extends Service implements RemoteAttend4SalaryService {
    private final Boolean isLog = "true".equals(new BaseBean().getPropValue("hrmSalary", "log"));

    @Override
    public List<Map<String, String>> getColumns() {
        Map<String, Object> paramsMap = new HashMap<String, Object>();
//        paramsMap.put("pageIndex", 1);
//        paramsMap.put("pageSize", 10);
        paramsMap.put("typeselect", "3");
        paramsMap.put("viewScope", "0");
        paramsMap.put("isNoAccount", "1");
        paramsMap.put("attendanceSerial", "");
        paramsMap.put("isFromMyAttendance", "1");
        Map<String, Object> temp = new HashMap<String, Object>();
        temp.put("data", JSONObject.toJSONString(paramsMap));
        temp.put("reportType", "month");
        List<Map> datas = (List<Map>) commandExecutor.execute(new GetKQReportCmd(temp, user)).get("columns");
        if (isLog) {
            log.info("同步考勤字段，{}", JSONUtils.toJSONString(datas));
        }
        List<Map<String, String>> columns = new ArrayList<>();
        datas.stream().filter(column -> Objects.nonNull(column.get("dataIndex"))).forEach(column -> {
            String dataIndex = column.get("dataIndex").toString();
            //请假
            if (dataIndex.equals("leave") && column.get("children") != null) {
                List<Map> list = (List<Map>) column.get("children");
                if (CollectionUtils.isNotEmpty(list)) {
                    list.stream()
                            .filter(leave -> leave.get("dataIndex") != null && StringUtils.isNotBlank(leave.get("dataIndex").toString()))
                            .forEach(leave -> {
                                Map<String, String> map = Maps.newHashMapWithExpectedSize(2);
                                map.put("code", leave.get("dataIndex").toString());
                                map.put("name", Util.null2String(column.get("title")) + "-" + leave.get("title") + "(" + leave.get("unit").toString() + ")");
                                columns.add(map);
                            });
                }
            }
            //加班
            else if (dataIndex.equals("overtime") && column.get("children") != null) {
                List<Map> list = (List<Map>) column.get("children");
                if (CollectionUtils.isNotEmpty(list)) {
                    for (int i = 0; i < list.size(); i++) {
                        Map overtimeMap = list.get(i);
                        if (overtimeMap.get("dataIndex") != null && StringUtils.isNotBlank(overtimeMap.get("dataIndex").toString()) && overtimeMap.get("children") == null) {
                            Map<String, String> map = Maps.newHashMapWithExpectedSize(2);
                            map.put("code", overtimeMap.get("dataIndex").toString());
                            map.put("name", Util.null2String(column.get("title")) + "-" + overtimeMap.get("title") + "(" + overtimeMap.get("unit").toString() + ")");
                            columns.add(map);
                        }
                        if (overtimeMap.get("dataIndex") != null && StringUtils.isNotBlank(overtimeMap.get("dataIndex").toString()) && overtimeMap.get("children") != null) {
                            List<Map> overtimes = (List<Map>) overtimeMap.get("children");
                            if (CollectionUtils.isNotEmpty(overtimes)) {
                                overtimes.stream().filter(leave -> leave.get("dataIndex") != null && StringUtils.isNotBlank(leave.get("dataIndex").toString()))
                                        .forEach(leave -> {
                                            Map<String, String> map = Maps.newHashMapWithExpectedSize(2);
                                            map.put("code", leave.get("dataIndex").toString());
                                            map.put("name", Util.null2String(column.get("title")) + "-" + Util.null2String(overtimeMap.get("title")) + "-" + leave.get("title") + "(" + leave.get("unit").toString() + ")");
                                            columns.add(map);
                                        });
                            }
                        }

                    }
                }
            }
            //普通考勤
            else {
                if (column.get("unit") != null && StringUtils.isNotBlank(column.get("unit").toString())) {
                    Map<String, String> map = Maps.newHashMapWithExpectedSize(2);
                    map.put("code", dataIndex);
                    map.put("name", column.get("title") + "(" + column.get("unit").toString() + ")");
                    columns.add(map);
                }
            }
        });

        //假期余额字段
        columns.addAll(getBalanceOfLeaveColumns());
        return columns;
    }

    @Override
    public List<Map<String, String>> getDatas(Attend4Salary attend4Salary) {
        ValidUtil.doValidator(attend4Salary);
        log.info("salaryAttend开始获取的考勤数据，参数{}", attend4Salary);
        List<Map<String, String>> list = new ArrayList<>();

        try {
            Map<String, Object> paramsMap = new HashMap<String, Object>();
            paramsMap.put("pageIndex", 1);
            paramsMap.put("pageSize", 500);
            paramsMap.put("typeselect", "6");
            paramsMap.put("fromDate", SalaryDateUtil.getFormatLocalDate(attend4Salary.getBeginDate()));
            paramsMap.put("toDate", SalaryDateUtil.getFormatLocalDate(attend4Salary.getEndDate()));
            paramsMap.put("viewScope", "3");
            List<String> resourceIds = attend4Salary.getOnlyEmpIds().stream().map(String::valueOf).collect(Collectors.toList());
            paramsMap.put("resourceId", String.join(",", resourceIds));
            paramsMap.put("isNoAccount", "1");
            paramsMap.put("attendanceSerial", "");
            paramsMap.put("isFromMyAttendance", "1");
            Map<String, Object> temp = new HashMap<String, Object>();
            temp.put("data", JSONObject.toJSONString(paramsMap));
            temp.put("reportType", "month");
            list = (List<Map<String, String>>) commandExecutor.execute(new GetKQReportCmd(temp, user)).get("datas");
            if (isLog) {
                log.info("salaryAttend获取的考勤数据，{}", JSONUtils.toJSONString(list));
            }
        } catch (Exception e) {
            log.error("salaryAttend获取考勤数据失败", e);
        }

        try {
            //假期余额信息
            List<Map<String, String>> balanceOfLeaveDatas = getBalanceOfLeaveDatas(attend4Salary);
            Map<String, Map<String, String>> balanceMap = SalaryEntityUtil.convert2Map(balanceOfLeaveDatas, m -> m.get("id"));

            //给有考勤的赋值
            List<String> attendEmpIds = list.stream().map(attend -> {
                String resourceId = attend.get("resourceId");
                Map<String, String> map = balanceMap.getOrDefault(resourceId, new HashMap<>());
                for (String key : map.keySet()) {
                    attend.put("balanceOfLeave_" + key, map.get(key));
                }
                return resourceId;
            }).collect(Collectors.toList());

            //没有考勤，但有假期余额的人赋值
            List<Map<String, String>> balanceOfLeaveList = balanceMap.keySet().stream()
                    .filter(k -> !attendEmpIds.contains(k))
                    .map(k -> {
                        Map<String, String> result = new HashMap<>();
                        result.put("resourceId", k);
                        Map<String, String> map = balanceMap.get(k);
                        for (String key : map.keySet()) {
                            result.put("balanceOfLeave_" + key, map.get(key));
                        }
                        return result;
                    })
                    .collect(Collectors.toList());
            list.addAll(balanceOfLeaveList);
        } catch (Exception e) {
            log.error("salaryAttend获取假期数据失败", e);
        }
        return list;
    }

    @Override
    public List<Map<String, String>> getBalanceOfLeaveColumns() {
        Map<String, Object> paramsMap = new HashMap<String, Object>();
        paramsMap.put("dateScope", "6");
        paramsMap.put("selectedYear", 2023);
        paramsMap.put("dataScope", "3");
        paramsMap.put("resourceId", 92);
        paramsMap.put("status", "9");
        paramsMap.put("isNoAccount", true);
        List<Map<String, String>> columns = (List<Map<String, String>>) commandExecutor.execute(new GetSearchListCmd(paramsMap, user)).get("columns");

        List<Map<String, String>> balanceOfLeaveColumns = columns.stream()
                .filter(column -> NumberUtils.isCreatable(column.get("key")))
                .map(column -> {
                    Map<String, String> map = Maps.newHashMapWithExpectedSize(2);
                    map.put("code", "balanceOfLeave_" + column.get("key"));
                    map.put("name", "假期余额-" + column.get("title"));
                    return map;
                }).collect(Collectors.toList());

        return balanceOfLeaveColumns;
    }


    @Override
    public List<Map<String, String>> getBalanceOfLeaveDatas(Attend4Salary attend4Salary) {
        Map<String, Object> paramsMap = new HashMap<String, Object>();
        paramsMap.put("currentPage", "1");
        paramsMap.put("pageSize", "500");
        paramsMap.put("selectedYear", SalaryDateUtil.date2Year(attend4Salary.getBeginDate()));
        paramsMap.put("dataScope", "3");
        paramsMap.put("resourceId", attend4Salary.getOnlyEmpIds().stream().map(String::valueOf).collect(Collectors.joining(",")));
        paramsMap.put("status", "9");
        paramsMap.put("isNoAccount", true);
        return (List<Map<String, String>>) commandExecutor.execute(new GetSearchListCmd(paramsMap, user)).get("datas");
    }
}
