package com.xiaoniu.subsystem.business.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.xiaoniu.common.core.constant.Constants;
import com.xiaoniu.common.core.result.R;
import com.xiaoniu.common.core.utils.DateUtils;
import com.xiaoniu.common.core.utils.StringUtils;
import com.xiaoniu.common.core.vo.AnalysisLineVO;
import com.xiaoniu.common.core.vo.LabelAndValueNameVO;
import com.xiaoniu.common.log.annotation.Log;
import com.xiaoniu.common.log.enums.BusinessType;
import com.xiaoniu.subsystem.business.domain.*;
import com.xiaoniu.subsystem.business.domain.dto.ExpenseStatisticsDTO;
import com.xiaoniu.subsystem.business.domain.vo.ProfessionVO;
import com.xiaoniu.subsystem.business.domain.vo.TypeStatisticsVO;
import com.xiaoniu.subsystem.business.service.*;

import com.xiaoniu.subsystem.system.domain.SysDictData;
import com.xiaoniu.subsystem.system.domain.Unit;
import com.xiaoniu.subsystem.system.service.ISysDictDataService;
import com.xiaoniu.subsystem.system.service.IUnitService;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.AllArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.time.Year;
import java.util.*;
import java.util.stream.Collectors;

import static com.xiaoniu.common.security.utils.SecurityUtils.getUnitId;

/**
 * 首页统计接口
 *
 * @packageName: com.xiaoniu.subsystem.business.controller
 * @className: HomeStatisticsController.java
 * @author: 孙松涛
 * @date: 2024-11-29 17:06
 * @version:
 */
@RestController
@AllArgsConstructor
@Tag(name = "首页统计接口", description = "首页统计接口")
@RequestMapping("/home/statistics")
public class HomeStatisticsController {


    private IProjectService projectService;
    private IProjectPersonnelInfoService personnelInfoService;
    // private IAnnualPlanAmountService amountService;
    private IExpenseService expenseService;
    private IUnitService unitService;
    private ISysDictDataService dictDataService;


    /**
     * 统计信息
     */
    @GetMapping("/message")
    @ApiOperationSupport(order = 1)
    @Operation(summary = "首页统计-统计信息", description = "传入dto")
    public R<List<LabelAndValueNameVO>> message(ExpenseStatisticsDTO dto) {
        List<LabelAndValueNameVO> voList = new ArrayList<>();
        List<Project> list = projectService.list(new LambdaQueryWrapper<Project>()
                .eq(StringUtils.isBlank(dto.getYear()), Project::getYear, Year.now().getValue())
                .eq(StringUtils.isNotBlank(dto.getYear()), Project::getYear, dto.getYear()));
        if (CollectionUtils.isEmpty(list)) {
            voList.add(new LabelAndValueNameVO().setName("未培训").setValue("0"));
            voList.add(new LabelAndValueNameVO().setName("培训中").setValue("0"));
            voList.add(new LabelAndValueNameVO().setName("已培训").setValue("0"));
            voList.add(new LabelAndValueNameVO().setName("计划金额").setValue("0"));
            voList.add(new LabelAndValueNameVO().setName("实际花费").setValue("0"));
            return R.data(voList);
        }
        List<ProjectPersonnelInfo> infos = personnelInfoService.list(new LambdaQueryWrapper<ProjectPersonnelInfo>()
                .in(ProjectPersonnelInfo::getProjectId,
                        list.stream().map(Project::getProjectId).collect(Collectors.toList())));
        voList.add(new LabelAndValueNameVO()
                .setName("未培训")
                .setValue(String.valueOf(infos.stream().filter(i -> StringUtils.equals("0",i.getIsAttend())).count())));
        voList.add(new LabelAndValueNameVO()
                .setName("培训中")
                .setValue(String.valueOf(infos.stream().filter(i ->
                        StringUtils.equals("1",i.getIsAttend()) && StringUtils.equals("0",i.getIsFinishSchool())).count())));
        voList.add(new LabelAndValueNameVO()
                .setName("已培训")
                .setValue(String.valueOf(infos.stream().filter(i -> StringUtils.equals("1",i.getIsFinishSchool())).count())));
        List<Expense> expenseList = expenseService.list(new LambdaQueryWrapper<Expense>()
                .in(Expense::getFlightId, list.stream().map(Project::getFlightId).collect(Collectors.toList()))
                .eq(StringUtils.isBlank(dto.getYear()), Expense::getYear, Year.now().getValue())
                .eq(StringUtils.isNotBlank(dto.getYear()), Expense::getYear, dto.getYear()));
        voList.add(new LabelAndValueNameVO()
                .setName("计划金额")
                .setValue(String.valueOf(expenseList.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(org.apache.commons.lang3.StringUtils.isEmpty(l.getOrganBudgetedAmount()) ?
                                        "0" : l.getOrganBudgetedAmount())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add))));
        voList.add(new LabelAndValueNameVO()
                .setName("实际花费")
                .setValue(String.valueOf(expenseList.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getSettlementAmount()) ?
                                        "0" : l.getSettlementAmount())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add))));
        return R.data(voList);
    }

    /**
     * 统计信息
     */
    @GetMapping("/profession")
    @ApiOperationSupport(order = 2)
    @Operation(summary = "首页统计-专业统计", description = "传入dto")
    public R<ProfessionVO> profession(ExpenseStatisticsDTO dto) {
        ProfessionVO vo = new ProfessionVO();
        vo.setLabels(new ArrayList<>());
        List<Long> longs = unitService.juniorUnit(getUnitId());
        List<Project> list = projectService.list(new LambdaQueryWrapper<Project>()
                .in(!CollectionUtils.isEmpty(longs),Project::getCreateDept,longs)
                .eq(StringUtils.isBlank(dto.getYear()), Project::getYear, Year.now().getValue())
                .eq(StringUtils.isNotBlank(dto.getYear()), Project::getYear, dto.getYear()));
        SysDictData data = new SysDictData();
        data.setDictType("1");
        List<SysDictData> list1 = dictDataService.selectDictDataList(data);
        if (CollectionUtils.isEmpty(list)) {
            list1.forEach(l -> vo.getLabels().add(new LabelAndValueNameVO().setName(l.getDictValue()).setValue("0")));
            return R.data(vo);
        }
        long counts = 0L;
        for (SysDictData l : list1) {
            List<Long> collect = list.stream().filter(p -> l.getDictLabel().equals(p.getMajorType()))
                    .map(Project::getProjectId).collect(Collectors.toList());
            long count = 0L;
            if (CollectionUtils.isNotEmpty(collect)){
                count = personnelInfoService.count(new LambdaQueryWrapper<ProjectPersonnelInfo>()
                        .in(ProjectPersonnelInfo::getProjectId, collect));
            }
            vo.getLabels().add(new LabelAndValueNameVO().setName(l.getDictValue())
                    .setValue(String.valueOf(count)));
            counts = counts + count;
        }
        vo.setTotal((int) counts);
        return R.data(vo);
    }

    /**
     * 统计信息
     */
    @GetMapping("/type")
    @ApiOperationSupport(order = 3)
    @Operation(summary = "首页统计-类型统计", description = "传入dto")
    public R<TypeStatisticsVO> type(ExpenseStatisticsDTO dto) {
        TypeStatisticsVO vo = new TypeStatisticsVO();
        vo.setLabels(new ArrayList<>());
        List<Long> longs = unitService.juniorUnit(getUnitId());
        List<Project> list = projectService.list(new LambdaQueryWrapper<Project>()
                .in(!CollectionUtils.isEmpty(longs),Project::getCreateDept,longs)
                .eq(StringUtils.isBlank(dto.getYear()), Project::getYear, Year.now().getValue())
                .eq(StringUtils.isNotBlank(dto.getYear()), Project::getYear, dto.getYear()));
        if (CollectionUtils.isEmpty(list)) {
            vo.getLabels().add(new LabelAndValueNameVO().setName("高级").setValue("0"));
            vo.getLabels().add(new LabelAndValueNameVO().setName("中级").setValue("0"));
            vo.getLabels().add(new LabelAndValueNameVO().setName("初级").setValue("0"));
            return R.data(vo);
        }
        List<ProjectPersonnelInfo> infos = personnelInfoService.list(new LambdaQueryWrapper<ProjectPersonnelInfo>()
                .in(ProjectPersonnelInfo::getProjectId,
                        list.stream().map(Project::getProjectId).collect(Collectors.toList())));
        vo.getLabels().add(new LabelAndValueNameVO()
                .setName("高级")
                .setValue(String.valueOf(infos.stream().filter(i -> "2".equals(i.getTraineeType())).count())));
        vo.getLabels().add(new LabelAndValueNameVO()
                .setName("中级")
                .setValue(String.valueOf(infos.stream().filter(i -> "1".equals(i.getTraineeType())).count())));
        vo.getLabels().add(new LabelAndValueNameVO()
                .setName("初级")
                .setValue(String.valueOf(infos.stream().filter(i -> "0".equals(i.getTraineeType())).count())));
        vo.setTotal(String.valueOf(infos.size()));
        return R.data(vo);
    }

    /**
     * 费用统计-人员统计
     */
    @GetMapping("/distribution")
    @ApiOperationSupport(order = 4)
    @Log(title = "首页统计-学员分布", businessType = BusinessType.OTHER)
    @Operation(summary = "首页统计-学员分布", description = "传入dto")
    public R<AnalysisLineVO> distribution(ExpenseStatisticsDTO dto) {
        AnalysisLineVO analysisLineVO = new AnalysisLineVO();
//        return R.data(analysisLineVO);
        List<AnalysisLineVO.DataList> dataList = new ArrayList<>();
        AnalysisLineVO.DataList list1 = new AnalysisLineVO.DataList();
        list1.setName("计划");
        list1.setType("line");
        list1.setYAxisData(new ArrayList<>());
        AnalysisLineVO.DataList list2 = new AnalysisLineVO.DataList();
        list2.setName("实际");
        list2.setType("line");
        list2.setYAxisData(new ArrayList<>());
        List<String> xAxisData = new ArrayList<>();
        List<Unit> units = unitService.list(new LambdaQueryWrapper<Unit>()
                .eq(Unit::getParentId, getUnitId()));
        for (Unit unit : units) {
            xAxisData.add(unit.getUnitName());
            List<Project> list = projectService.list(new LambdaQueryWrapper<Project>()
                    .eq(Project::getCreateDept,unit.getUnitId())
                    .eq(StringUtils.isBlank(dto.getYear()), Project::getYear, Year.now().getValue())
                    .eq(StringUtils.isNotBlank(dto.getYear()), Project::getYear, dto.getYear()));
            if (CollectionUtils.isEmpty(list)) {
                list1.getYAxisData().add("0");
                list2.getYAxisData().add("0");
            }else {
                list1.getYAxisData().add(String.valueOf(list.stream().map(l ->
                                BigDecimal.valueOf(Double.parseDouble(StringUtils.isEmpty(l.getTrainingPost()) ?
                                        "0" : l.getTrainingPost())))
                        .reduce(BigDecimal.ZERO, BigDecimal::add)));
                List<Long> ids = new ArrayList<>(list.stream().map(Project::getProjectId).toList());
                List<Project> all = getAll(ids);
                ids.addAll(all.stream().map(Project::getProjectId).toList());
                List<ProjectPersonnelInfo> list3 = personnelInfoService.list(new LambdaQueryWrapper<ProjectPersonnelInfo>()
                        .in(ProjectPersonnelInfo::getProjectId, ids));
                list2.getYAxisData().add(String.valueOf(list3.size()));
            }
        }
        dataList.add(list1);
        dataList.add(list2);
        analysisLineVO.setXAxisData(xAxisData);
        analysisLineVO.setDataList(dataList);
        return R.data(analysisLineVO);
    }

    public List<Project> getAll(List<Long> ids) {
        List<Project> list = new ArrayList<>();
        List<Project> projects = projectService.list(new LambdaQueryWrapper<Project>()
                .in(Project::getParentId,ids).eq(Project::getIsDeleted, Constants.ZERO));
        if (CollectionUtils.isEmpty(projects)) {
            return list;
        }
        list.addAll(projects);
        list.addAll(getAll(projects.stream().map(Project::getProjectId).distinct().toList()));
        return list;
    }
}
