package com.cmeeting.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import cn.hutool.poi.excel.StyleSet;
import cn.hutool.poi.excel.style.StyleUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cmeeting.mapper.primary.SysUserSyncMapper;
import com.cmeeting.mapper.primary.UserAccessRecordMapper;
import com.cmeeting.pojo.SysUserSyncCategory;
import com.cmeeting.pojo.UserAccessRecord;
import com.cmeeting.service.ISysUserSyncCategoryService;
import com.cmeeting.service.IUserAccessRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Font;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class UserAccessRecordServiceImpl extends ServiceImpl<UserAccessRecordMapper, UserAccessRecord> implements IUserAccessRecordService {

    @Resource
    private ISysUserSyncCategoryService iSysUserSyncCategoryService;

    @Override
    public Page<Map<String, String>> statistics(String search, Date startTime, Date endTime, Integer current, Integer size) {
        List<String> dateList = DateUtil.rangeToList(startTime, endTime, DateField.DAY_OF_YEAR).stream()
                .map(date -> DateUtil.format(date, "yyyy-MM-dd"))
                .collect(Collectors.toList());
        String start = DateUtil.format(startTime, "yyyy-MM-dd");
        String end = DateUtil.format(endTime, "yyyy-MM-dd");

        Page<Map<String, String>> page = baseMapper.statisticsByDate(new Page<>(current, size), search, start, end, dateList);
        List<Map<String, String>> records = page.getRecords();

        if (CollUtil.isNotEmpty(records)) {
            List<SysUserSyncCategory> categoryList = iSysUserSyncCategoryService.list(new LambdaQueryWrapper<SysUserSyncCategory>().select(SysUserSyncCategory::getDeptId, SysUserSyncCategory::getParentId, SysUserSyncCategory::getName));
            Map<String, String> parentIdMap = categoryList.stream().collect(Collectors.toMap(SysUserSyncCategory::getDeptId, SysUserSyncCategory::getParentId));
            Map<String, String> nameMap = categoryList.stream().collect(Collectors.toMap(SysUserSyncCategory::getDeptId, SysUserSyncCategory::getName));
            for (Map<String, String> map : records) {
                String deptId = map.get("deptId");
                String pathName = iSysUserSyncCategoryService.getPathName(deptId, parentIdMap, nameMap);
                map.put("deptName", pathName);
            }
        }

        for (Map<String, String> userInfo : records) {
            // 横向加法
            Integer sum = userInfo.values().stream()
                    // 小于4是为了和用户编号区分开
                    .filter(value -> NumberUtil.isNumber(value) && value.length() < 4)
                    .map(Integer::parseInt)
                    .reduce(Integer::sum)
                    .orElse(0);
            userInfo.put("sum", sum.toString());
        }

        if (records.isEmpty()) {
            return page;
        }

        // 初始化一行用来纵向加和
        Map<String, String> lastRowMap = new LinkedHashMap<>();
        for (String key : records.get(0).keySet()) {
            lastRowMap.put(key, "");
        }
        for (Map<String, String> stringMap : records) {
            for (Map.Entry<String, String> entry : stringMap.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                if (NumberUtil.isNumber(value) && value.length() < 4) {
                    lastRowMap.put(key, String.valueOf(NumberUtil.add(lastRowMap.get(key), value)));
                }
            }
        }
        lastRowMap.put("userId", "总计");
        records.add(lastRowMap);
        page.setRecords(records);
        return page;
    }

    @Override
    public List<Map<String, String>> statisticsByCompany(Date startTime, Date endTime, List<String> deptMap) {

        List<String> dateList = DateUtil.rangeToList(startTime, endTime, DateField.DAY_OF_YEAR).stream()
                .map(date -> DateUtil.format(date, "yyyy-MM-dd"))
                .collect(Collectors.toList());
        String start = DateUtil.format(startTime, "yyyy-MM-dd");
        String end = DateUtil.format(endTime, "yyyy-MM-dd");

        Page<Map<String, String>> page = baseMapper.statisticsByDate(new Page<>(1, -1), null, start, end, dateList);
        List<Map<String, String>> records = page.getRecords();

        if (CollUtil.isNotEmpty(records)) {
            List<SysUserSyncCategory> categoryList = iSysUserSyncCategoryService.list(new LambdaQueryWrapper<SysUserSyncCategory>().select(SysUserSyncCategory::getDeptId, SysUserSyncCategory::getParentId, SysUserSyncCategory::getName));
            Map<String, String> parentIdMap = categoryList.stream().collect(Collectors.toMap(SysUserSyncCategory::getDeptId, SysUserSyncCategory::getParentId));
            Map<String, String> nameMap = categoryList.stream().collect(Collectors.toMap(SysUserSyncCategory::getDeptId, SysUserSyncCategory::getName));
            for (Map<String, String> map : records) {
                String deptId = map.get("deptId");
                String pathName = iSysUserSyncCategoryService.getPathName(deptId, parentIdMap, nameMap);
                map.put("deptName", pathName);
            }
        }

        Map<String, List<Map<String, String>>> groupList = new LinkedHashMap<>();

        for (Map<String, String> record : records) {
            String deptName = record.get("deptName");
            if (CollUtil.isNotEmpty(deptMap)) {
                for (String s : deptMap) {
                    if ((deptName+"/").contains(s + "/")) {
                        List<Map<String, String>> maps = groupList.get(deptName);
                        if (maps == null) {
                            maps = new ArrayList<>();
                        }
                        maps.add(record);
                        log.info("deptName: {}, size: {}", deptName, maps.size());
                        groupList.put(s, maps);
                    }
                }
            }
        }
        List<Map<String, String>> ret = new ArrayList<>();
        for (Map.Entry<String, List<Map<String, String>>> entry : groupList.entrySet()) {
            for (Map<String, String> map : entry.getValue()) {
                Map<String, String> temp = new LinkedHashMap<>();
                temp.put("deptName", entry.getKey());
                for (Map.Entry<String, String> mapEntry : map.entrySet()) {
                    String key = mapEntry.getKey();
                    String value = mapEntry.getValue();
                    if (NumberUtil.isNumber(value) && value.length() < 4) {
                        temp.put(key, String.valueOf(NumberUtil.add(temp.get(key), value)));
                    }
                }
                ret.add(temp);
            }
        }

        for (Map<String, String> userInfo : ret) {
            // 横向加法
            Integer sum = userInfo.values().stream()
                    // 小于4是为了和用户编号区分开
                    .filter(value -> NumberUtil.isNumber(value) && value.length() < 4)
                    .map(Integer::parseInt)
                    .reduce(Integer::sum)
                    .orElse(0);
            userInfo.put("sum", sum.toString());
        }
        if (ret.isEmpty()) {
            return new ArrayList<>();
        }

        // 初始化一行用来纵向加和
        Map<String, String> lastRowMap = new LinkedHashMap<>();
        lastRowMap.put("userId", "总计");
        for (String key : ret.get(0).keySet()) {
            lastRowMap.put(key, "");
        }
        for (Map<String, String> stringMap : ret) {
            for (Map.Entry<String, String> entry : stringMap.entrySet()) {
                String key = entry.getKey();
                String value = entry.getValue();
                if (NumberUtil.isNumber(value) && value.length() < 4) {
                    lastRowMap.put(key, String.valueOf(NumberUtil.add(lastRowMap.get(key), value)));
                }
            }
        }
        ret.add(lastRowMap);
        return ret;
    }

    @Override
    public void exportUserAccessRecord(List<Map<String, String>> statistics, List<String> dateList, HttpServletResponse response) {
        ExcelWriter writer = ExcelUtil.getWriter(Boolean.TRUE);
        ServletOutputStream out = null;
        try {
            List<List<String>> rows = new ArrayList<>();

            for (Map<String, String> statistic : statistics) {
                String deptPath = statistic.get("deptName");
                deptPath = deptPath.replace("/中集集团/", "");
                String[] split = deptPath.split("/");
                List<String> row = CollUtil.newArrayList(split[0], split.length>=2?split[1]:"", split.length>=3?split[2]:"", split.length>=4?split[3]:"", split.length>=5?split[4]:"",
                        statistic.get("userId"), statistic.get("name"));
                List<String> validSortedValues = getValidSortedValues(statistic);
                row.addAll(validSortedValues);
                row.add(statistic.get("sum"));
                rows.add(row);
            }

            CellStyle headCellStyle = writer.getHeadCellStyle();
            Font headFont = writer.createFont();
            headFont.setFontName("微软雅黑");
            headFont.setFontHeightInPoints((short) 10);
            headCellStyle.setFont(headFont);

            List<String> head = CollUtil.newArrayList("版块", "二级", "三级", "四级", "五级", "姓名", "工号");
            head.addAll(dateList);
            head.add("总计");
            writer.writeHeadRow(head);

            writer.write(rows, true);

            String fileName = String.format("会议助手访问次数%s.xlsx", DateUtil.today());
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf8"));
            System.out.println("exportExecute==ing=====================");
            out = response.getOutputStream();
            writer.flush(out, true);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        } finally {
            writer.close();
            IoUtil.close(out);
        }
    }

    @Override
    public void exportUserAccessRecordByCompany(List<Map<String, String>> data, List<String> dateList, HttpServletResponse response) throws IOException {
        ExcelWriter writer = ExcelUtil.getWriter(Boolean.TRUE);
        ServletOutputStream out = null;
//        try {
            List<List<String>> rows = new ArrayList<>();

            for (Map<String, String> statistic : data) {
                String deptName = statistic.get("deptName");
                String[] split = deptName.trim().split("/");
                log.info("deptName: {}", deptName);
                List<String> row;
                if (split.length >= 4) {
                    row = CollUtil.newArrayList(split[2], split[3], split.length >= 5 ? split[4] : "");
                } else {
                    row = CollUtil.newArrayList("总计", "", "");
                }
                List<String> validSortedValues = getValidSortedValues(statistic);
                row.addAll(validSortedValues);
                row.add(statistic.get("sum"));
                rows.add(row);
            }

            CellStyle headCellStyle = writer.getHeadCellStyle();
            Font headFont = writer.createFont();
            headFont.setFontName("微软雅黑");
            headFont.setFontHeightInPoints((short) 10);
            headCellStyle.setFont(headFont);

            List<String> head = CollUtil.newArrayList("模块", "二级", "三级");
            head.addAll(dateList);
            head.add("总计");
            writer.writeHeadRow(head);

            writer.write(rows, true);

            String fileName = String.format("会议助手访问次数(按部门统计)%s.xlsx", DateUtil.today());
            response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf8"));
            System.out.println("exportExecute==ing=====================");
            out = response.getOutputStream();
            writer.flush(out, true);
//        } catch (Exception e) {
//            e.printStackTrace();
//            throw new RuntimeException(e.getMessage());
//        } finally {
            writer.close();
            IoUtil.close(out);
//        }
    }

    public static List<String> getValidSortedValues(Map<String, String> map) {
        // 定义日期格式器
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        return map.entrySet().stream()
                // 过滤掉格式不正确的日期key
                .filter(entry -> {
                    try {
                        // 尝试解析日期，解析成功则保留，失败则过滤
                        LocalDate.parse(entry.getKey(), formatter);
                        return true;
                    } catch (DateTimeParseException e) {
                        // 日期格式不正确，过滤该条目
                        return false;
                    }
                })
                // 按日期升序排序
                .sorted((entry1, entry2) -> {
                    LocalDate date1 = LocalDate.parse(entry1.getKey(), formatter);
                    LocalDate date2 = LocalDate.parse(entry2.getKey(), formatter);
                    return date1.compareTo(date2);
                })
                // 提取排序后的value
                .map(Map.Entry::getValue)
                // 收集到List中
                .collect(Collectors.toList());
    }

    public static void main(String[] args) {
        String name = "/1/2/3/4";
        String[] split = name.split("/");
        for (String s : split) {
            System.out.println(s);
        }
        System.out.println(split.length);
    }
}
