package com.ruoyi.system.controller;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.ruoyi.system.PinYinUtil;
import com.ruoyi.system.domain.excel.CostDetailForExcel;
import com.ruoyi.system.domain.query.ProjectCostExportQuery;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.ShiroUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.system.domain.ProjectCostModel;
import com.ruoyi.system.domain.TblProject;
import com.ruoyi.system.domain.TblProjectCost;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.ITblProjectCostService;
import com.ruoyi.system.service.ITblProjectService;

import javax.servlet.http.HttpServletResponse;

/**
 * 工时Controller
 *
 * @author ruoyi
 * @date 2021-02-18
 */
@Controller
@RequestMapping("/system/cost")
public class TblProjectCostController extends BaseController {
    private String prefix = "system/cost";

    @Autowired
    private ITblProjectCostService tblProjectCostService;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private ITblProjectService tblProjectService;

    private static final String STR_DATE_FORMAT = "yyyy-MM-dd";

    @RequiresPermissions("system:cost:view")
    @GetMapping()
    public String cost(ModelMap mmap) {
        List<SysUser> users = userService.selectAvailableUserFilterByLeader(new SysUser());
        sortUser(users);
        mmap.put("users", users);
        List<TblProject> projects = tblProjectService.selectTblProjectList(new TblProject().setOrder());
        mmap.put("projects", projects);
        return prefix + "/cost";
    }

    /**
     * 查询工时列表
     */
    @RequiresPermissions("system:cost:list")
    @PostMapping("/list")
    @ResponseBody
    public TableDataInfo list(TblProjectCost tblProjectCost) {
        startPage();
        List<TblProjectCost> list = tblProjectCostService.selectTblProjectCostList(tblProjectCost);
        return getDataTable(list);
    }

    @RequiresPermissions("system:cost:summember")
    @GetMapping("/summember")
    public String summember(ModelMap mmap) throws ParseException {
        List<SysUser> users = userService.selectUserList(new SysUser());
        sortUser(users);
        mmap.put("users", users);
        String[] d = getWeek(0, null);
        mmap.put("endDate", d[1]);
        mmap.put("startDate", d[0]);
        mmap.put("type", "summember");
        return prefix + "/sum";
    }

    @RequiresPermissions("system:cost:sumproject")
    @GetMapping("/sumproject")
    public String sumproject(ModelMap mmap) throws ParseException {
        List<TblProject> projects = tblProjectService.selectMyTblProjectList(ShiroUtils.getUserId());
        mmap.put("projects", projects);

        String[] d = getWeek(0, null);
        mmap.put("endDate", d[1]);
        mmap.put("startDate", d[0]);
        mmap.put("type", "sumproject");
        return prefix + "/sum";
    }

    @PostMapping("/changeweek")
    @ResponseBody
    public String[] getWeek(int week, String date) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat(STR_DATE_FORMAT);

        String[] d = new String[2];
        Calendar cal = Calendar.getInstance();
        if (week != 0 && StringUtils.isNotEmpty(date)) {
            cal.setTime(sdf.parse(date));
        }
        cal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
        if (week == 0) {
            if (cal.after(Calendar.getInstance())) {
                cal.add(Calendar.DATE, -7);
            }
        } else {
            cal.add(Calendar.DATE, 7 * week);
        }
        d[1] = sdf.format(cal.getTime());
        cal.add(Calendar.DATE, -6);
        d[0] = sdf.format(cal.getTime());
        return d;
    }

    /**
     * 统计工时列表
     */
    @RequiresPermissions("system:cost:sumproject")
    @PostMapping("/sumproject")
    @ResponseBody
    public TableDataInfo sumproject(TblProjectCost tblProjectCost) {
        return sum(tblProjectCost, 0);
    }

    /**
     * 统计工时列表
     */
    @RequiresPermissions("system:cost:summember")
    @PostMapping("/summember")
    @ResponseBody
    public TableDataInfo summember(TblProjectCost tblProjectCost) {
        return sum(tblProjectCost, 1);
    }

    /**
     * 统计工时列表
     */
    private TableDataInfo sum(TblProjectCost tblProjectCost, int searchType) {
        tblProjectCost.getParams().put("userId", ShiroUtils.getUserId());
        tblProjectCost.getParams().put("order", searchType == 0 ? "project_id,user" : "user,project_id");
        List<TblProjectCost> list = null;
        if (searchType == 0) {
            list = tblProjectCostService.selectTblProjectCostSumProject(tblProjectCost);
        } else {
            list = tblProjectCostService.selectTblProjectCostSumMember(tblProjectCost);
        }
        List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
        SimpleDateFormat sdf = new SimpleDateFormat(STR_DATE_FORMAT);
        String key = null;
        Map<String, Object> row = null;
        List<TblProjectCost> rowList = null;
        List<Map<String, Object>> sumList = null;
        for (TblProjectCost c : list) {
            if ((searchType == 0 && (!c.getProjectId().equals(key)))
                    || (searchType != 0 && (!c.getUser().toString().equals(key)))) {
                key = searchType == 0 ? c.getProjectId() : c.getUser().toString();
                row = new HashMap<String, Object>();
                rowList = new ArrayList<TblProjectCost>();
                sumList = new ArrayList<Map<String, Object>>();
                row.put("list", rowList);
                row.put("sumList", sumList);
                row.put("name", searchType == 0 ? c.getProjectName() : c.getUserName());
                row.put("costDay", new BigDecimal(0));
                row.put("startDate", sdf.format(tblProjectCost.getEndDate()));
                row.put("endDate", sdf.format(tblProjectCost.getStartDate()));
                result.add(row);
            }
//            int i = 0;
//            while (i < rowList.size() && rowList.get(i).getCostDay().compareTo(c.getCostDay()) > 0) {
//                i++;
//            }
//            rowList.add(i, c);
            rowList.add(c);
            if ((searchType == 0 && !sumList.stream().anyMatch(x -> x.get("sumId") == c.getUser()))
                    || (searchType != 0 && !sumList.stream().anyMatch(x -> x.get("sumId") == c.getProjectId()))) {
                Map<String, Object> sumRow = new HashMap<String, Object>();
                sumRow.put("sumId", searchType == 0 ? c.getUser() : c.getProjectId());
                sumRow.put("sumName", searchType == 0 ? c.getUserName() : c.getProjectName());
                sumRow.put("sumDay", c.getCostDay());
                //sumList.put(c.getProjectId(),sumRow);
                sumList.add(sumRow);
            } else {
                Map<String, Object> sumRow = sumList.stream().filter(x -> x.get("sumId").equals(c.getProjectId())).findFirst().get();
                sumRow.put("sumDay", ((BigDecimal) sumRow.get("sumDay")).add(c.getCostDay()));
            }

            row.put("costDay", ((BigDecimal) row.get("costDay")).add(c.getCostDay()));
            String date = sdf.format(c.getStartDate());
            if (date.compareTo((String) row.get("startDate")) < 0) {
                row.put("startDate", date);
            }
            date = sdf.format(c.getEndDate());
            if (date.compareTo((String) row.get("endDate")) > 0) {
                row.put("endDate", date);
            }
        }
        for (Map<String, Object> r : result) {
            ((List<Map<String, Object>>) r.get("sumList")).sort(new Comparator<Map<String, Object>>() {
                public int compare(Map<String, Object> arg0, Map<String, Object> arg1) {
                    return ((BigDecimal) arg1.get("sumDay")).compareTo((BigDecimal) arg0.get("sumDay"));
                }

            }.thenComparing(new Comparator<Map<String, Object>>() {
                public int compare(Map<String, Object> arg0, Map<String, Object> arg1) {
                    return ((String) arg1.get("sumName")).compareTo((String) arg0.get("sumName"));
                }
            }));
            ((List<TblProjectCost>) r.get("list")).sort(new Comparator<TblProjectCost>() {
                public int compare(TblProjectCost arg0, TblProjectCost arg1) {
                    if (searchType == 0) {
                        return arg1.getUser().compareTo(arg0.getUser());
                    } else {
                        return arg1.getProjectId().compareTo(arg0.getProjectId());
                    }
                }
            }.thenComparing(new Comparator<TblProjectCost>() {
                public int compare(TblProjectCost arg0, TblProjectCost arg1) {
                    return arg1.getCostDay().compareTo(arg0.getCostDay());
                }
            }));
        }
        Collections.sort(result, new Comparator<Map<String, Object>>() {
            public int compare(Map<String, Object> arg0, Map<String, Object> arg1) {
                return ((BigDecimal) arg1.get("costDay")).compareTo((BigDecimal) arg0.get("costDay"));
            }
        }.thenComparing(new Comparator<Map<String, Object>>() {
            public int compare(Map<String, Object> arg0, Map<String, Object> arg1) {
                return ((String) arg1.get("name")).compareTo((String) arg0.get("name"));
            }
        }));

        return getDataTable(result);
    }

    /**
     * 导出工时列表
     */
    @RequiresPermissions("system:cost:export")
    @Log(title = "工时", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    @ResponseBody
    public AjaxResult export(TblProjectCost tblProjectCost) {
        List<TblProjectCost> list = tblProjectCostService.selectTblProjectCostList(tblProjectCost);
        ExcelUtil<TblProjectCost> util = new ExcelUtil<TblProjectCost>(TblProjectCost.class);
        return util.exportExcel(list, "cost");
    }

    /**
     * 新增工时
     *
     * @throws ParseException
     */
    @GetMapping("/add")
    public String add(ModelMap mmap) throws ParseException {
        List<SysUser> users = userService.selectAvailableUserFilterByLeader(new SysUser());

        if (users.size() > 0) {
            Long userId = users.get(0).getUserId();
//            TblProjectCost tblProjectCost = tblProjectCostService.selectTblProjectCostLastData(userId);
//            // Date lastDate = null;
//            if (tblProjectCost != null) {
//                mmap.put("projectList", tblProjectCost.getProjectId().split(","));
//                // lastDate = tblProjectCost.getEndDate();
//            } else {
//                mmap.put("projectList", "".split(","));
//            }
            mmap.put("projectList", "".split(","));
//			Date beginDate = null;
//			Calendar calendar = new GregorianCalendar();
//			SimpleDateFormat sdf = new SimpleDateFormat(STR_DATE_FORMAT);
//			if (lastDate != null) {
//				calendar.setTime(lastDate);
//				calendar.add(Calendar.DATE, 1);
//				beginDate = calendar.getTime();
//				mmap.put("beginDate", sdf.format(beginDate));
//				calendar.add(Calendar.DATE, 6);
//				Date endDate = calendar.getTime();
//				mmap.put("endDate", sdf.format(endDate));
//			} 
            String[] d = getWeek(0, null);
            mmap.put("endDate", d[1]);
            mmap.put("beginDate", d[0]);

            mmap.put("userId", userId);
        }
        // TblProject tp = new TblProject().setOrder(userId, ShiroUtils.getLoginName());
//        TblProject tp = new TblProject().setOrder();
//        tp.setStatus("1");
//        List<TblProject> projects = tblProjectService.selectTblProjectList(tp);
//
//        mmap.put("projects", projects);

        sortUser(users);
        mmap.put("users", users);
        // 取身份信息
        SysUser user = ShiroUtils.getSysUser();
        mmap.put("loginUser", user);
        return prefix + "/add";
    }

    @PostMapping("/getuserproject")
    @ResponseBody
    public AjaxResult getUserProject(@RequestBody Long userId) {
        List<TblProject> list = tblProjectService.selectTblProjectListByUserProject(userId);
        sortProject(list);
        return AjaxResult.success(list);
    }

    private void sortProject(List<TblProject> projects) {
        if (projects == null) {
            return;
        }
        Collections.sort(projects, new Comparator<TblProject>() {
            public int compare(TblProject arg0, TblProject arg1) {
                if (StringUtils.isEmpty(arg0.getName()) || StringUtils.isEmpty(arg1.getName())) {
                    return -1;
                }
                try {
                    return PinYinUtil.cn2Spell(arg0.getName()).compareTo(PinYinUtil.cn2Spell(arg1.getName()));
                } catch (Exception ex) {
                    PinYinUtil.cn2Spell(arg0.getName());
                    return -1;
                }
            }
        });
    }

    private void sortUser(List<SysUser> users) {
        if (users == null) {
            return;
        }
        Collections.sort(users, new Comparator<SysUser>() {
            public int compare(SysUser arg0, SysUser arg1) {
                if (StringUtils.isEmpty(arg0.getUserName()) || StringUtils.isEmpty(arg1.getUserName())) {
                    return -1;
                }
//                System.out.println(PinYinUtil.cn2Spell(arg0.getUserName()));
                return PinYinUtil.cn2Spell(arg0.getUserName()).compareTo(PinYinUtil.cn2Spell(arg1.getUserName()));
            }
        });
    }


    /**
     * 新增保存工时
     */
    @RequiresPermissions("system:cost:add")
    @Log(title = "工时", businessType = BusinessType.INSERT)
    @PostMapping("/add")
    @ResponseBody
    public AjaxResult addSave(ProjectCostModel projectCostModel) {
        SysUser user = new SysUser();
        user.setUserId(projectCostModel.getUser());
        List<SysUser> users = userService.selectAvailableUserList(user);
        if (users.size() != 1) {
            return error("添加工时失败，用户不存在");
        }
        if (projectCostModel.getStartDate().after(projectCostModel.getEndDate())) {
            return error("添加工时失败，起始时间大于结束时间");
        }
        TblProjectCost tblProjectCost = new TblProjectCost();
        tblProjectCost.setStartDate(projectCostModel.getStartDate());
        tblProjectCost.setEndDate(projectCostModel.getEndDate());
        tblProjectCost.setUser(projectCostModel.getUser());
//		List<TblProjectCost> list = tblProjectCostService.selectTblProjectCostList(tblProjectCost);
//		if (list.size() > 0) {
//			return error("添加工时失败，该时间段内已有工时记录");
//		}
        String userName = users.get(0).getUserName();
        String createBy = ShiroUtils.getLoginName();
        String groupId = UUID.randomUUID().toString().replaceAll("-", "");
        Date createTime = new Date();
        List<TblProjectCost> list = new ArrayList<TblProjectCost>();
        for (int i = 0; i < projectCostModel.getProjectId().length; i++) {
            if (projectCostModel.getCostDay()[i].compareTo(new BigDecimal(0)) > 0) {
                tblProjectCost = new TblProjectCost(groupId + "-" + String.valueOf(100 + i).substring(1));
                tblProjectCost.setGroupId(groupId);
                tblProjectCost.setUser(projectCostModel.getUser());
//                SysUser u = userService.selectUserById(projectCostModel.getUser());
//                if(u != null)
//                {
//                    tblProjectCost.setDeptId(u.getDeptId());
//                }
                tblProjectCost.setUserName(userName);
                tblProjectCost.setStartDate(projectCostModel.getStartDate());
                tblProjectCost.setEndDate(projectCostModel.getEndDate());
                tblProjectCost.setProjectId(projectCostModel.getProjectId()[i]);
                tblProjectCost.setCostDay(projectCostModel.getCostDay()[i]);
                if (projectCostModel.getRemark().length > i) {
                    tblProjectCost.setRemark(projectCostModel.getRemark()[i]);
                } else {
                    tblProjectCost.setRemark("");
                }
                tblProjectCost.setCreateBy(createBy);
                tblProjectCost.setCreateTime(createTime);
                list.add(tblProjectCost);
            }
        }
        return toAjax(tblProjectCostService.insertTblProjectCostList(list));
    }

    @RequiresPermissions("system:cost:add")
    @Log(title = "工时", businessType = BusinessType.INSERT)
    @PostMapping("/changePerson")
    @ResponseBody
    public AjaxResult changePerson(ProjectCostModel projectCostModel) {
        SysUser user = new SysUser();
        user.setUserId(projectCostModel.getUser());
        List<SysUser> users = userService.selectAvailableUserList(user);
        if (users.size() != 1) {
            return error("失败，用户不存在");
        }
        return toAjax(tblProjectCostService.updateUserUpdatetime(projectCostModel.getUser()));
    }

    /**
     * 修改工时
     */
    @GetMapping("/edit/{id}")
    public String edit(@PathVariable("id") String id, ModelMap mmap) {
        TblProjectCost tblProjectCost = tblProjectCostService.selectTblProjectCostById(new TblProjectCost(id));
        List<TblProject> list = new ArrayList<>();
        if (tblProjectCost != null) {
            list = tblProjectService.selectTblProjectListByUserProject(tblProjectCost.getUser());
        }
        mmap.put("tblProjectCost", tblProjectCost);
        mmap.put("projectList", list);
        return prefix + "/edit";
    }

    /**
     * 修改保存工时
     */
    @RequiresPermissions("system:cost:edit")
    @Log(title = "工时", businessType = BusinessType.UPDATE)
    @PostMapping("/edit")
    @ResponseBody
    public AjaxResult editSave(TblProjectCost tblProjectCost) {
        tblProjectCost.setUpdateBy(ShiroUtils.getLoginName());
        return toAjax(tblProjectCostService.updateTblProjectCost(tblProjectCost));
    }

    /**
     * 删除工时
     */
    @RequiresPermissions("system:cost:remove")
    @Log(title = "工时", businessType = BusinessType.DELETE)
    @PostMapping("/remove")
    @ResponseBody
    public AjaxResult remove(String ids) {
        return toAjax(tblProjectCostService.deleteTblProjectCostByIds(ids));
    }

    @GetMapping("/exportExcel")
    public String exportExcel(ModelMap mmap) throws ParseException {
        List<SysUser> users = userService.selectAvailableUserFilterByLeader(new SysUser());
        List<TblProject> projects = tblProjectService.selectPMOTblProjectList(ShiroUtils.getUserId());
        mmap.put("users", users);
        mmap.put("projects", projects);
        String[] d = getWeek(0, null);
        mmap.put("endDate", d[1]);
        mmap.put("startDate", d[0]);
        return prefix + "/exportExcel";
    }

    @PostMapping("/downLoadExcel")
    @ResponseBody
    public AjaxResult downLoadExcel(ProjectCostExportQuery query) {
        TblProjectCost tblProjectCost = new TblProjectCost();
        tblProjectCost.setStartDate(query.getStartDate());
        tblProjectCost.setEndDate(query.getEndDate());
        tblProjectCost.getParams().put("userId", ShiroUtils.getUserId());
//        tblProjectCost.getParams().put("order", "start_date desc");
        List<TblProjectCost> list = null;
        String preStr = "";
        if ("user-sum".equalsIgnoreCase(query.getSumType())) {
            SysUser u = userService.selectUserById(Long.valueOf(query.getQueryId()));
            preStr = u != null ? u.getUserName() : "";
            tblProjectCost.setUser(Long.valueOf(query.getQueryId()));
            list = tblProjectCostService.selectTblProjectCostSumProject(tblProjectCost);
        } else {
            TblProject p = tblProjectService.selectTblProjectById(query.getQueryId());
            preStr = p != null ? p.getName() : "";
            tblProjectCost.setProjectId(query.getQueryId());
            list = tblProjectCostService.selectTblProjectCostSumMember(tblProjectCost);
        }
        List<CostDetailForExcel> excels = new ArrayList<CostDetailForExcel>();
        if (list != null) {
            excels = list.stream().map(x -> {
                CostDetailForExcel info = new CostDetailForExcel();
                info.setName("user-sum".equalsIgnoreCase(query.getSumType()) ? x.getProjectName() : x.getUserName());
                info.setRemark(x.getRemark());
                info.setTimeSpan(x.getStartDate(), x.getEndDate());
                info.setCost(x.getCostDay());

                return info;
            }).collect(Collectors.toList());
        }
        ExcelUtil<CostDetailForExcel> util = new ExcelUtil<CostDetailForExcel>(CostDetailForExcel.class);
        return util.exportExcel(excels, String.format("%s工时明细", preStr));
    }

}
