package cn.palmte.work.service;

import cn.palmte.work.bean.ResponseMsg;
import cn.palmte.work.model.*;
import cn.palmte.work.utils.DateKit;
import cn.palmte.work.utils.InterfaceUtil;
import cn.palmte.work.utils.StrKit;
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 top.jfunc.common.db.bean.Page;
import top.jfunc.common.db.utils.Pagination;
import top.jfunc.common.utils.CollectionUtil;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author Yuanping Zhang
 * @date 2021/11/1
 */
@Service
public class HumanCostService {
    private static final Logger logger = LoggerFactory.getLogger(HumanCostService.class);

    @Autowired
    private ProjectUserTimeRepositoryImpl projectUserTimeRepositoryImpl;

    @Autowired
    private ProjectUserTimeRepository projectUserTimeRepository;

    @Autowired
    private ProjectRepository projectRepository;

    @Autowired
    private AdminRepository adminRepository;

    @Autowired
    private Pagination pagination;

    public Page<ProjectUserTime> project(ConcurrentHashMap<String, String> searchInfo, Admin admin, int pageNumber, int pageSize) {
        Page<ProjectUserTime> list = projectUserTimeRepositoryImpl.project(searchInfo, admin, pageNumber, pageSize);
        return list;
    }

    public List<ProjectUserTime> staff(ConcurrentHashMap<String, String> searchInfo, Admin admin) {
        List<ProjectUserTime> list = projectUserTimeRepositoryImpl.staff(searchInfo, admin);
        return list;
    }

    public List<ProjectUserTime> list(ConcurrentHashMap<String, String> searchInfo, Admin admin, int pageNumber, int pageSize) {
        List<ProjectUserTime> list = projectUserTimeRepositoryImpl.list(searchInfo, admin, pageNumber, pageSize);
        return list;
    }

    public Map<String, BigDecimal> map(ConcurrentHashMap<String, String> searchInfo, Admin admin, int pageNumber, int pageSize) {
        List<ProjectUserTime> list = projectUserTimeRepositoryImpl.list(searchInfo, admin, pageNumber, pageSize);
        Map<String, BigDecimal> map = new HashMap<>(16);
        for (ProjectUserTime put : list) {
            map.put(put.getProjectName() + put.getUserId(), put.getUserCost());
        }
        return map;
    }


    public Page<ProjectUserTime> individual(ConcurrentHashMap<String, String> searchInfo, Integer id, int pageNumber, int pageSize) {
        Page<ProjectUserTime> list = projectUserTimeRepositoryImpl.individual(searchInfo, id, pageNumber, pageSize);
        return list;
    }

    public static void main(String[] args) {
        String date = "2021-12";
        Date date1 = DateKit.getDate(date, DateKit.DATE_FORMAT_YEAR_MONTH2);
        if (date1.getTime() - System.currentTimeMillis() > 0) {
            System.out.println(date1.getTime() - System.currentTimeMillis());
        } else {
            System.out.println(date1.getTime());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public ResponseMsg check(Collection<Map> excelMap, Map<String, String> title, String date) {
        int successCount = 0;
        int errorCount = 0;
        Admin admin;
        BigDecimal userCost;
        BigDecimal userSalary;
        List<String> errorList = new ArrayList<>();
        Set<String> projectSet = new HashSet<>();
        Map<String, BigDecimal> staffCost = new HashMap<>();
        List<ProjectUserTime> saveList = new ArrayList<>();

        Date date1 = DateKit.getDate(date, DateKit.DATE_FORMAT_YEAR_MONTH2);
        if (date1.getTime() - System.currentTimeMillis() > 0) {
            ResponseMsg msg = ResponseMsg.buildFailedMsg("填写日期须小于当前日期！");
            msg.setData(errorList);
            return msg;
        }
        if(excelMap.size() == 0){
            ResponseMsg msg = ResponseMsg.buildFailedMsg("请填写人力成本数据！");
            msg.setData(errorList);
            return msg;
        }
        if (title.size() < excelMap.size() - 1) {
            ResponseMsg msg = ResponseMsg.buildFailedMsg("人员名单存在重复！");
            msg.setData(errorList);
            return msg;
        }
        for (Map m : excelMap) {
            try {
                Object o1 = m.get("项目名称");
                if (o1 == null || StrKit.isBlank(o1.toString())) {
                    throw new Exception("项目名称不能为空");
                }
                if ("成本".equals(o1.toString())) {
                    continue;
                }
                String projectName = (String)o1;
                Project project = projectRepository.findByProjectName(projectName);
                if (project == null) {
                    throw new Exception(projectName + "不存在");
                } else if (project.getStatus() == Project.STATUS_ESTIMATE || (project.getStatus() == Project.STATUS_ESTIMATE && project.getApproveStatusEstimate() != 2) || (project.getStatus() == Project.STATUS_FINAL && project.getApproveStatusFinal() == 2)) {
                    throw new Exception(projectName + "不在项目人力成本的可导入状态");
                }
                if (projectSet.contains(projectName)) {
                    throw new Exception("项目名称存在重复！");
                } else {
                    projectSet.add(projectName);
                }
                for (String key : title.keySet()) {
                    if (key == null || StrKit.isBlank(key)) {
                        throw new Exception("人员名称不能为空");
                    }
                    admin = adminRepository.getAdminByRealName(key);
                    if (admin == null) {
                        throw new Exception(key + "不存在");
                    }

                    Object o2 = m.get(key);
                    if (o2 == null || StrKit.isBlank(o2.toString())) {
                        throw new Exception(projectName + " " + key + "的月份额不能为空");
                    }
                    if (o2.toString().matches("(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){1,2})?") && BigDecimal.valueOf(1).compareTo(new BigDecimal(o2.toString())) > -1 && BigDecimal.valueOf(0).compareTo(new BigDecimal(o2.toString())) < 1) {
                        userCost = new BigDecimal(o2.toString());
                    } else {
                        throw new Exception(projectName + " " + key + "的月份额需为0到1之间最多两位小数的数字");
                    }
                    String o3 = title.get(key);
                    if (o3 == null || StrKit.isBlank(o3)) {
                        throw new Exception(projectName + " " + key + "的成本不能为空");
                    }
                    if (o3.matches("(([1-9]{1}\\d*)|([0]{1}))(\\.(\\d){1,2})?") && BigDecimal.valueOf(0).compareTo(new BigDecimal(o3)) < 1) {
                        userSalary = new BigDecimal(o3);
                    } else {
                        throw new Exception(projectName + " " + key + "的成本需为大于0的最多两位小数的的数字");
                    }
//                    ProjectUserTime put = projectUserTimeRepository.findByUserIdAndProjectIdAndTime(admin.getId(), project.getId(), date);
                    ProjectUserTime put = new ProjectUserTime();
                    put.setCreatedBy(InterfaceUtil.getAdminId());
                    put.setCreatedTime(new Date());
                    put.setTime(date);
                    put.setProjectId(project.getId());
                    put.setProjectName(project.getName());
                    put.setUserName(admin.getRealName());
                    put.setUserId(admin.getId());
                    put.setUserCost(userCost);
                    put.setUserSalary(userSalary);

                    staffCost.put(key, userCost.add(staffCost.getOrDefault(key, BigDecimal.valueOf(0))));
                    saveList.add(put);
                }

                successCount++;
            } catch (Exception e) {
                logger.error("", e);
                errorCount++;
                errorList.add(e.getMessage());
            }
        }
        if (errorCount > 0) {
            final ResponseMsg msg = ResponseMsg.buildSuccessMsg(String.format("失败：%d", errorCount));
            msg.setData(errorList);
            return msg;
        }
        for (String key : staffCost.keySet()) {
            try {
                if (staffCost.getOrDefault(key, BigDecimal.valueOf(0)).compareTo(BigDecimal.valueOf(1)) != 0) {
                    throw new Exception(key + "的月份额总计不为1");
                }
            } catch (Exception e) {
                logger.error("", e);
                errorCount++;
                errorList.add(e.getMessage());
            }
        }
        if (errorCount == 0) {
            int row = projectUserTimeRepository.deleteByTime(date);
            logger.info("删除重复条目：" + row + "条");
            projectUserTimeRepository.save(saveList);
            final ResponseMsg msg = ResponseMsg.buildSuccessMsg(String.format("成功：%d, 失败：%d", successCount, errorCount));
            msg.setData(errorList);
            return msg;
        } else {
            final ResponseMsg msg = ResponseMsg.buildSuccessMsg(String.format("失败：%d", errorCount));
            msg.setData(errorList);
            return msg;
        }
    }

    public String[] getHeaders(List<ProjectUserTime> staff) {
        String[] headers = new String[staff.size() + 3];
        headers[0] = "项目名称";
        headers[1] = "人力总计";
        headers[2] = "成本总计";
        int i = 3;
        for (ProjectUserTime person : staff) {
            headers[i++] = person.getUserName();
        }
        return headers;
    }

    public String[] getColumns(List<ProjectUserTime> project) {
        String[] columns = new String[project.size()];
        int i = 0;
        for (ProjectUserTime p : project) {
            columns[i++] = p.getProjectName();
        }
        return columns;
    }

    public BigDecimal sum(ConcurrentHashMap<String, String> searchInfo, Admin admin) {
        List<ProjectUserTime> sum = projectUserTimeRepositoryImpl.sum(searchInfo, admin);
        if(CollectionUtil.isNotEmpty(sum)){
            BigDecimal result = sum.stream().map((ProjectUserTime t) -> t.getUserCost().multiply(t.getUserSalary())).reduce(BigDecimal.ZERO, BigDecimal::add);
            return result;
        }
        return new BigDecimal(0);
    }

    public String[] template(List<String> data) {
        String adminSql = "select su.* from sys_user su left join sys_user_role sur on su.id = sur.user_id where su.is_deleted = 0 and su.enabled = 1 and sur.role_id <> 1 group by su.id";
        List<Admin> admins = pagination.find(adminSql, Admin.class);
        String[] headers = new String[admins.size() + 1];
        headers[0] = "项目名称";
        for (int i = 1; i <= admins.size(); i++) {
            headers[i] = admins.get(i - 1).getRealName();
        }
        Admin admin = InterfaceUtil.getAdmin();
        List<Project> projectList = null;
        if (admin.getRoleLevel() <= 3 || admin.getRoleLevel() == 6) {
            String sql = "select proj.id, proj.name from project proj where (proj.status = ? or (proj.status = ? and proj.approve_status_budget = ?) or (proj.status = ? and proj.approve_status_final <> ?)) order by proj.id asc";
            projectList = pagination.find(sql, Project.class, Project.STATUS_SETTLE, Project.STATUS_BUDGET, 2, Project.STATUS_FINAL, 2);
        } else {
            String sql = "select proj.id, proj.name from project proj where (proj.status = ? or (proj.status = ? and proj.approve_status_budget = ?) or (proj.status = ? and proj.approve_status_final <> ?)) and " +
                    " (proj.creator_id=? OR proj.id in (SELECT pv1.project_id FROM project_visible pv1 WHERE pv1.type=1 AND pv1.tid=? UNION SELECT pv2.project_id FROM project_visible pv2 WHERE pv2.type=2 AND pv2.tid=?)) order by proj.id asc";
            //项目可见性，根据角色和人员id
            int roleId = admin.getRoleId();
            Integer adminId = admin.getId();
            //自己创建的肯定能看见
            projectList = pagination.find(sql, Project.class, Project.STATUS_SETTLE, Project.STATUS_BUDGET, 2, Project.STATUS_FINAL, 2, adminId, roleId, adminId);
        }
        for (Project project : projectList) {
            data.add(project.getName());
        }
        return headers;
    }
}
