package com.project.zcustom.service.service.employee.impl;

import com.project.common.utils.DateUtils;
import com.project.zcustom.domain.employee.PlatEmployeeType;
import com.project.zcustom.domain.employee.PlatEmployeeTypeFlow;
import com.project.zcustom.mapper.employee.PlatEmployeeTypeMapper;
import com.project.zcustom.service.service.employee.IPlatEmployeeTypeFlowService;
import com.project.zcustom.service.service.employee.IPlatEmployeeTypeService;
import com.project.common.core.domain.search.PageParamVo;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.project.common.utils.StringUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * 员工概况Service业务层处理
 *
 * @author change
 * @date 2024-10-21
 */
@Service
public class PlatEmployeeTypeServiceImpl extends ServiceImpl<PlatEmployeeTypeMapper, PlatEmployeeType> implements IPlatEmployeeTypeService {

    @Resource
    private IPlatEmployeeTypeFlowService iPlatEmployeeTypeFlowService;

    /**
     * 组装查询条件
     */
    private LambdaQueryWrapper<PlatEmployeeType> getLambdaQueryWrapper(PlatEmployeeType platEmployeeType) {
        LambdaQueryWrapper<PlatEmployeeType> lqw = new LambdaQueryWrapper<PlatEmployeeType>();
        if (StringUtils.isNotBlank(platEmployeeType.getAppOrg())) {
            lqw.eq(PlatEmployeeType::getAppOrg, platEmployeeType.getAppOrg());
        }
        return lqw;
    }

    /**
     * 分页查询员工概况列表
     *
     * @param platEmployeeType 员工概况
     * @return 员工概况集合
     */
    @Override
    public IPage<PlatEmployeeType> pagingPlatEmployeeTypeList(PlatEmployeeType platEmployeeType) {
        IPage<PlatEmployeeType> page = new Page<>(platEmployeeType.getPageNum(), platEmployeeType.getPageSize());
        LambdaQueryWrapper<PlatEmployeeType> lqw = getLambdaQueryWrapper(platEmployeeType);
        // 排序 默认时间倒序
        lqw.orderByDesc(PlatEmployeeType::getCreateTime);
        return baseMapper.selectPage(page, lqw);
    }

    /**
     * 分页查询员工概况列表
     *
     * @param lqw
     * @return 员工概况集合
     */
    @Override
    public IPage<PlatEmployeeType> pagingPlatEmployeeTypeList(PageParamVo pageParamVo, LambdaQueryWrapper<PlatEmployeeType> lqw) {
        IPage<PlatEmployeeType> page = new Page<>(pageParamVo.getPageNum(), pageParamVo.getPageSize());
        // 排序 默认时间倒序
        lqw.orderByDesc(PlatEmployeeType::getCreateTime);
        return baseMapper.selectPage(page, lqw);
    }

    /**
     * 查询员工概况列表
     *
     * @param platEmployeeType 员工概况
     * @return 员工概况
     */
    @Override
    public List<PlatEmployeeType> selectPlatEmployeeTypeList(PlatEmployeeType platEmployeeType) {
        LambdaQueryWrapper<PlatEmployeeType> lqw = getLambdaQueryWrapper(platEmployeeType);
        // 排序 默认时间倒序
        lqw.orderByDesc(PlatEmployeeType::getCreateTime);
        return baseMapper.selectList(lqw);
    }

    /**
     * 查询员工概况列表
     *
     * @param platEmployeeType 员工概况
     * @return 员工概况
     */
    @Override
    public List<PlatEmployeeType> selectPlatEmployeeTypeList(PlatEmployeeType platEmployeeType, Long limitNum) {
        LambdaQueryWrapper<PlatEmployeeType> lqw = getLambdaQueryWrapper(platEmployeeType);
        // 排序 默认时间倒序
        lqw.orderByDesc(PlatEmployeeType::getCreateTime);
        lqw.last("limit " + limitNum);
        return baseMapper.selectList(lqw);
    }

    /**
     * 根据指定字段查询信息
     *
     * @param field      字段名称
     * @param filedValue 字段值
     * @return 员工概况
     */
    @Override
    public PlatEmployeeType getPlatEmployeeTypeByField(String field, String filedValue) {
        QueryWrapper<PlatEmployeeType> lqw = new QueryWrapper<PlatEmployeeType>();
        lqw.eq(field, filedValue);
        lqw.last("limit 1");
        return this.getOne(lqw, false);
    }

    /**
     * 根据指定字段查询信息
     *
     * @param field      字段名称
     * @param filedValue 字段值
     * @return 员工概况
     */
    @Override
    public PlatEmployeeType getPlatEmployeeTypeByField(String field, String filedValue,String fieldString) {
        QueryWrapper<PlatEmployeeType> lqw = new QueryWrapper<PlatEmployeeType>();
        if(!(Objects.equals(field,"app_org") && Objects.equals(filedValue,"0000"))){
            lqw.eq(field, filedValue);
        }
        lqw.select(fieldString);
        lqw.last("limit 1");
        return this.getOne(lqw, false);
    }

    /**
     * 根据指定字段查询信息列表
     *
     * @param field      字段名称
     * @param filedValue 字段值
     * @return 员工概况
     */
    @Override
    public List<PlatEmployeeType> selectPlatEmployeeTypeListByField(String field, String filedValue, Long limitNum) {
        QueryWrapper<PlatEmployeeType> lqw = new QueryWrapper<PlatEmployeeType>();
        lqw.eq(field, filedValue);
        lqw.last("limit " + limitNum);
        return this.list(lqw);
    }

    /**
     * 根据指定字段查询信息列表
     *
     * @param field      字段名称
     * @param filedValue 字段值
     * @return 员工概况
     */
    @Override
    public List<PlatEmployeeType> selectPlatEmployeeTypeListByField(String field, String filedValue) {
        QueryWrapper<PlatEmployeeType> lqw = new QueryWrapper<PlatEmployeeType>();
        lqw.eq(field, filedValue);
        return this.list(lqw);
    }

    /**
     * 判断指定字段值是否存在
     *
     * @param field      字段名称
     * @param filedValue 字段值
     */
    @Override
    public void checkFieldExist(String field, String filedValue, String tips, Long id) {
        QueryWrapper<PlatEmployeeType> lqw = new QueryWrapper<PlatEmployeeType>();
        lqw.eq(field, filedValue);
        lqw.ne("id", id);
        if (this.getOne(lqw, false) != null) {
            throw new RuntimeException(tips + "已存在");
        }
    }

    /**
     * 添加数据
     *
     * @param appOrg
     * @param mapField
     */
    @Override
    public void addPlatEmployeeType(String appOrg, Map<String, Object> mapField) {
        PlatEmployeeType platEmployeeType = this.getPlatEmployeeTypeByField("app_org", appOrg);
        try {
            if (StringUtils.isNotNull(platEmployeeType)) {
                this.setPlatEmployeeType(mapField, platEmployeeType);
                Long grossNum = Long.sum(platEmployeeType.getEntryInternalNum() , platEmployeeType.getVisitorNum());
                platEmployeeType.setGrossNum(grossNum);
                this.updateById(platEmployeeType);
            } else {
                platEmployeeType = new PlatEmployeeType();
                this.setPlatEmployeeType(mapField, platEmployeeType);
                platEmployeeType.setAppOrg(appOrg);
                Long grossNum = Long.sum(platEmployeeType.getEntryInternalNum() , platEmployeeType.getVisitorNum());
                platEmployeeType.setGrossNum(grossNum);
                this.save(platEmployeeType);
            }
            iPlatEmployeeTypeFlowService.handleEmployeeFlow(appOrg, mapField);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 设置数据
     */
    private void setPlatEmployeeType(Map<String, Object> mapField, PlatEmployeeType platEmployeeType) {
        List<String> fieldList = Arrays.asList("inside", "loan", "association", "property", "entryInternal", "entryToLoan", "entryAssist", "entryProperty", "visitor", "gross", "man","women");

        // 员工类型
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 0, PlatEmployeeType::setInsideNum, Long.class);
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 1, PlatEmployeeType::setLoanNum, Long.class);
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 2, PlatEmployeeType::setAssociationNum, Long.class);
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 3, PlatEmployeeType::setPropertyNum, Long.class);

        // 入楼情况
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 4, PlatEmployeeType::setEntryInternalNum, Long.class);
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 5, PlatEmployeeType::setEntryToLoanNum, Long.class);
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 6, PlatEmployeeType::setEntryAssistNum, Long.class);
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 7, PlatEmployeeType::setEntryPropertyNum, Long.class);
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 8, PlatEmployeeType::setVisitorNum, Long.class);
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 9, PlatEmployeeType::setGrossNum, Long.class);

        // 员工性别情况
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 10, PlatEmployeeType::setManNum, Long.class);
        StringUtils.setFieldValue(platEmployeeType, mapField, fieldList, 11, PlatEmployeeType::setWomenNum, Long.class);

    }


    /**
     * 员工类型
     */
    @Override
    public List<Map<String, Object>> getEmployeePieData(String appOrg) {
        String fieldString = "inside_num,loan_num,association_num,property_num";
        if(Objects.equals(appOrg,"0000")){
            fieldString = "sum(inside_num) as inside_num,sum(loan_num) as loan_num,sum(association_num) as association_num,sum(property_num) as property_num";
        }
        PlatEmployeeType employeeType = this.getPlatEmployeeTypeByField("app_org", appOrg,fieldString);
        List<Long> valueList = StringUtils.getDefaultListLong(4);
        if (StringUtils.isNotNull(employeeType)) {
            valueList = Arrays.asList(employeeType.getInsideNum(), employeeType.getLoanNum(), employeeType.getAssociationNum(), employeeType.getPropertyNum());
        }
        List<String> xList = Arrays.asList("内部员工", "借调人员", "外协人员", "物业人员");
        List<String> colorList = Arrays.asList("#00ffdf", "#ffd296", "#7565ef", "#0084ff");
        List<Map<String, Object>> tempList = new ArrayList<>();
        StringUtils.createdPieData(xList, colorList, valueList, tempList);
        return tempList;
    }

    /**
     * 获取入楼情况
     */
    @Override
    public Map<String, Object> getEnterBuildData(String appOrg) {
        String fieldString = "entry_internal_num,entry_to_loan_num,entry_assist_num,entry_property_num,visitor_num,gross_num";
        if(Objects.equals(appOrg,"0000")){
            fieldString = "sum(entry_internal_num) as entry_internal_num,sum(entry_to_loan_num) as entry_to_loan_num,sum(entry_assist_num) as entry_assist_num,sum(entry_property_num) as entry_property_num,sum(visitor_num) as visitor_num,sum(gross_num) as gross_num";
        }
        PlatEmployeeType employeeType = this.getPlatEmployeeTypeByField("app_org", appOrg,fieldString);
        Map<String, Object> tempMap = new HashMap<>();
        if (StringUtils.isNull(employeeType)) {
            StringUtils.getMapData("内部员工", "entryInternalNum", 0, tempMap);
            StringUtils.getMapData("借调人员", "entryToLoanNum", 0, tempMap);
            StringUtils.getMapData("外协人员", "entryAssistNum", 0, tempMap);
            StringUtils.getMapData("物业人员", "entryPropertyNum", 0, tempMap);
            StringUtils.getMapData("访客", "visitorNum", 0, tempMap);
            StringUtils.getMapData("人员总数", "grossNum", 0, tempMap);
        } else {
            StringUtils.getMapData("内部员工", "entryInternalNum", employeeType.getEntryInternalNum(), tempMap);
            StringUtils.getMapData("借调人员", "entryToLoanNum", employeeType.getEntryToLoanNum(), tempMap);
            StringUtils.getMapData("外协人员", "entryAssistNum", employeeType.getEntryAssistNum(), tempMap);
            StringUtils.getMapData("物业人员", "entryPropertyNum", employeeType.getEntryPropertyNum(), tempMap);
            StringUtils.getMapData("访客", "visitorNum", employeeType.getVisitorNum(), tempMap);
            StringUtils.getMapData("人员总数", "grossNum", employeeType.getGrossNum(), tempMap);
        }
        return tempMap;
    }


    /**
     * 近一周人流量统计
     */
    @Override
    public Map<String, Object> getChartsFlowData(String appOrg) {
        List<String> nameList = Arrays.asList("内部人员", "借调人员", "外协人员", "物业人员","访客");
        // 获取7天前的日期
        List<String> dateList = DateUtils.generateDateList(7);
        List<String> colorList = Arrays.asList("#00ffdf", "#ffd296", "#7565ef", "#00ffff","#f4cb57");
        List<String> keyList = Arrays.asList("inside", "loan", "association", "property","visitor");
        QueryWrapper<PlatEmployeeTypeFlow> flowQueryWrapper = new QueryWrapper<>();
        if(!Objects.equals(appOrg,"0000")){
            flowQueryWrapper.eq("app_org", appOrg);
            flowQueryWrapper.select("time_sign,inside_num,loan_num,association_num,property_num,visit_num");
        }else{
            flowQueryWrapper.groupBy("time_sign");
            flowQueryWrapper.select("time_sign,sum(inside_num) as inside_num,sum(loan_num) as loan_num,sum(association_num) as association_num,sum(property_num) as property_num,sum(visit_num) as visit_num");
        }
        flowQueryWrapper.orderByAsc("time_sign");
        flowQueryWrapper.last("limit 7");
        List<PlatEmployeeTypeFlow> flowList = iPlatEmployeeTypeFlowService.list(flowQueryWrapper);
        List<List<Long>> valueList = Arrays.asList(StringUtils.getDefaultListLong(7), StringUtils.getDefaultListLong(7), StringUtils.getDefaultListLong(7), StringUtils.getDefaultListLong(7), StringUtils.getDefaultListLong(7));
        if (!flowList.isEmpty()) {
            for (int i = 0;i < flowList.size();i++){
                valueList.get(0).set(i,flowList.get(i).getInsideNum());
                valueList.get(1).set(i,flowList.get(i).getLoanNum());
                valueList.get(2).set(i,flowList.get(i).getAssociationNum());
                valueList.get(3).set(i,flowList.get(i).getPropertyNum());
                valueList.get(4).set(i,flowList.get(i).getVisitNum());
            }
        }
        Map<String,Object> yMap = new HashMap<>();
        for (int i = 0; i < nameList.size(); i++){
            Map<String,Object> tempMap = new HashMap<>();
            tempMap.put("name",nameList.get(i));
            tempMap.put("color",colorList.get(i));
            tempMap.put("dataList",valueList.get(i));
            yMap.put(keyList.get(i),tempMap);
        }
        yMap.put("xList",dateList);
        return yMap;

    }

    /**
     * 员工年龄分布情况
     */
    @Override
    public List<Map<String, Object>> getAgePieData(String appOrg) {
        String fieldString = "between2030_num,between3040_num,between4050_num,exceed50_num";
        if(Objects.equals(appOrg,"0000")){
            fieldString = "sum(between2030_num) as between2030_num,sum(between3040_num) as between3040_num,sum(between4050_num) as between4050_num,sum(exceed50_num) as exceed50_num";
        }
        PlatEmployeeType employeeType = this.getPlatEmployeeTypeByField("app_org", appOrg,fieldString);
        List<Long> valueList = StringUtils.getDefaultListLong(4);
        if (StringUtils.isNotNull(employeeType)) {
            valueList = Arrays.asList(employeeType.getBetween2030Num(), employeeType.getBetween3040Num(), employeeType.getBetween4050Num(), employeeType.getExceed50Num());
        }
        List<String> xList = Arrays.asList("20-30岁", "31-40岁", "41-50岁", "51岁以上");
        List<String> colorList = Arrays.asList("#FFB948", "#2F82FE", "#7565EF", "#00F6EC");
        List<Map<String, Object>> tempList = new ArrayList<>();
        StringUtils.createdPieData(xList, colorList, valueList, tempList);
        return tempList;
    }

    /**
     * 员工性别情况
     */
    @Override
    public Map<String, Object> getSexChartData(String appOrg) {
        String fieldString = "man_num,women_num";
        if(Objects.equals(appOrg,"0000")){
            fieldString = "sum(man_num) as man_num,sum(women_num) as women_num";
        }
        PlatEmployeeType employeeType = this.getPlatEmployeeTypeByField("app_org", appOrg,fieldString);
        Map<String, Object> tempMap = new HashMap<>();
        if (StringUtils.isNull(employeeType)) {
            StringUtils.createdTableData(Arrays.asList("男", "女"), Arrays.asList(0L,0L), "#d67c15", tempMap);
        } else {
            StringUtils.createdTableData(Arrays.asList("男", "女"), Arrays.asList(employeeType.getManNum(), employeeType.getWomenNum()), "#d67c15", tempMap);
        }
        return tempMap;
    }


}
