package cn.iocoder.yudao.module.visit.service.home;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.api.dict.DictDataApi;
import cn.iocoder.yudao.module.system.api.dict.dto.DictDataRespDTO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.visit.controller.admin.customerinfo.vo.CustomerInfoPageReqVO;
import cn.iocoder.yudao.module.visit.controller.admin.home.vo.*;
import cn.iocoder.yudao.module.visit.controller.admin.info.vo.InfoPageReqVO;
import cn.iocoder.yudao.module.visit.dal.dataobject.customerinfo.CustomerInfoDO;
import cn.iocoder.yudao.module.visit.dal.dataobject.info.InfoDO;
import cn.iocoder.yudao.module.visit.dal.dataobject.product.ProductDO;
import cn.iocoder.yudao.module.visit.dal.mysql.customerinfo.CustomerInfoMapper;
import cn.iocoder.yudao.module.visit.dal.mysql.info.InfoMapper;
import cn.iocoder.yudao.module.visit.dal.mysql.product.ProductMapper;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;

/**
 * 主页 Service 实现类
 *
 * @author 超级管理员
 */
@Service
@Validated
public class HomeServiceImpl implements HomeService {

    @Resource
    private CustomerInfoMapper customerInfoMapper;
    @Resource
    private InfoMapper  infoMapper;
    @Resource
    private ProductMapper productMapper;
    @Resource
    private AdminUserMapper userMapper;
    @Resource
    private DictDataApi dictDataApi;
    @Resource
    private DeptService deptService;

    //首页第一排数据
    @Override
    public HomeFirstRespVO getHomeInfoFirst(HomeReqVO reqVO) {
        HomeFirstRespVO homeFirstRespVO = new HomeFirstRespVO();

        //按拜访时间查这段时间的拜访次数
        InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
        infoPageReqVO.setVisitDate(reqVO.getSearchTime());
        infoPageReqVO.setPageSize(-1);//不分页
        infoPageReqVO.setCompanyName(reqVO.getCompanyName());
        PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);//精准查询
        //客户拜访总次数
        homeFirstRespVO.setVisitCount(String.valueOf(infoDOPageResult.getTotal()));
        List<InfoDO> list = Optional.ofNullable(infoDOPageResult.getList())
                .orElse(Collections.emptyList());

        homeFirstRespVO.setSykfcs(String.valueOf(
                list.stream()
                        .filter(infoDO -> Integer.valueOf(0).equals(infoDO.getVisitType()))
                        .count()));

        homeFirstRespVO.setYlkfcs(String.valueOf(
                list.stream()
                        .filter(infoDO -> Integer.valueOf(1).equals(infoDO.getVisitType()))
                        .count()));

        //业务员数量(不按时间）
//        Long loginUserDeptId = SecurityFrameworkUtils.getLoginUserDeptId();//查出登录用户的deptId
//        Set<Long> deptCondition = Collections.emptySet();//默认不限制
//        if (loginUserDeptId == null || !loginUserDeptId.equals(100L)) {//说明是总公司，不限制
//            deptCondition = getDeptCondition(loginUserDeptId);//不是总公司了，就递归查询该部门以及子部门的所有id
//        }
//        List<AdminUserDO> userDOS = userMapper.selectListInDeptIds(deptCondition);
        long count = list.stream()
                .map(InfoDO::getCreator)    // 提取 creator 字段
                .filter(Objects::nonNull) // 可选：过滤掉 null
                .distinct()            // 去重
                .count();// 统计个数
        homeFirstRespVO.setYwysl(String.valueOf(count));
        //按创建时间查这段时间的客户数量
//        CustomerInfoPageReqVO customerInfoPageReqVO = new CustomerInfoPageReqVO();
//        customerInfoPageReqVO.setCreateTime(reqVO.getSearchTime());
//        customerInfoPageReqVO.setPageSize(-1);//不分页
//        customerInfoPageReqVO.setCompanyName(reqVO.getCompanyName());
//        PageResult<CustomerInfoDO> customerInfoDOPageResult = customerInfoMapper.selectHomePage(customerInfoPageReqVO);//精准查询
        //按拜访记录中客户的数量
        long companyCount = list.stream()
                .map(InfoDO::getCompanyName)    // 提取 companyName 字段
                .filter(Objects::nonNull) // 可选：过滤掉 null
                .distinct()            // 去重
                .count();// 统计个数
        //拜访客户总数量
        homeFirstRespVO.setBfkhsl(String.valueOf(companyCount));
        //商业客户数量
//        String sykhsl = customerInfoDOPageResult.getList().stream().filter(customerInfoDO -> customerInfoDO.getCustomerType() == 0).count() + "";
        String sykhsl = list.stream().filter(infoDO -> infoDO.getCustomerStatus() == 0).map(InfoDO::getCompanyName).filter(Objects::nonNull).distinct().count()+ "";
        //医疗客户数量
//        String ylkhsl = customerInfoDOPageResult.getList().stream().filter(customerInfoDO -> customerInfoDO.getCustomerType() == 1).count() + "";
        String ylkhsl = list.stream().filter(infoDO -> infoDO.getCustomerStatus() == 1).map(InfoDO::getCompanyName).filter(Objects::nonNull).distinct().count()+ "";
        homeFirstRespVO.setSykhsl(sykhsl);
        homeFirstRespVO.setYlkhsl(ylkhsl);

        return homeFirstRespVO;
    }
    /**
     * 获得部门条件：查询指定部门的子部门编号们，包括自身
     *
     * @param deptId 部门编号
     * @return 部门编号集合
     */
    private Set<Long> getDeptCondition(Long deptId) {
        if (deptId == null) {
            return Collections.emptySet();
        }
        Set<Long> deptIds = convertSet(deptService.getChildDeptList(deptId), DeptDO::getId);
        deptIds.add(deptId); // 包括自身
        return deptIds;
    }
    //拜访周统计
    @Override
    public HomeBfztjRespVO getHomeInfoBfztj(HomeReqVO reqVO) {
        //如果查询时间是空，则start = LocalDateTime.now().minusWeeks(10);
        LocalDateTime start = null;
        LocalDateTime end = null;
         if (reqVO.getSearchTime() == null) {
            start = LocalDateTime.now().minusWeeks(9);
            end = LocalDateTime.now();
        }else {
            start = reqVO.getSearchTime()[0];
            end = reqVO.getSearchTime()[1];
        }


        // 对齐到每周一
        start = start.with(DayOfWeek.MONDAY);
        List<String> weeks = new ArrayList<>();
        List<Integer> counts = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            LocalDateTime weekStart = start.plusWeeks(i).with(LocalTime.MIN);;
            LocalDateTime weekEnd = weekStart.plusDays(6).with(LocalTime.MAX);
            LocalDateTime[] week = new LocalDateTime[]{weekStart, weekEnd};
            if (weekStart.isAfter(end)) break;

            int count = 0;//拜访次数
            InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
            infoPageReqVO.setVisitDate(week);
            infoPageReqVO.setPageSize(-1);//不分页
            infoPageReqVO.setCompanyName(reqVO.getCompanyName());
            PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);//精准查询
            count = Math.toIntExact(infoDOPageResult.getTotal());
            weeks.add("WEEK" + (i + 1));
            counts.add(count);
        }

        HomeBfztjRespVO vo = new HomeBfztjRespVO();
        vo.setWeeks(weeks);
        vo.setVisitCounts(counts);
        vo.setTotalWeeks(weeks.size());
        return vo;
    }

    //客户性质等级占比情况
    @Override
    public HomeKhxzdjzbqkRespVO getHomeInfoKhxzdjzbqk(HomeReqVO reqVO) {
        //1.先查出所有的客户信息
        InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
        infoPageReqVO.setPageSize(-1);
        infoPageReqVO.setVisitDate(reqVO.getSearchTime());
        infoPageReqVO.setCompanyName(reqVO.getCompanyName());
        PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
        List<InfoDO> records = infoDOPageResult.getList();

        // 2.分组计数：Map<customerType字典值, 数量>
        Map<Integer, Long> typeCountMap = records.stream()
                .collect(Collectors.groupingBy(InfoDO::getCustomerStatus, Collectors.counting()));

        // 3. 加载字典并转换为 Map
        List<DictDataRespDTO> dictList = dictDataApi.getDictDataList("customer_type");
        Map<String, String> dictMap = dictList.stream()
                .collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel));

        // 4. 组装返回列表
        List<HomeKhxzdjzbqkRespVO.TypeCountItem> list = typeCountMap.entrySet().stream()
                .map(entry -> {
                    HomeKhxzdjzbqkRespVO.TypeCountItem item = new HomeKhxzdjzbqkRespVO.TypeCountItem();
                    item.setName(dictMap.getOrDefault(entry.getKey().toString(), "未知"));
                    item.setValue(entry.getValue().intValue());
                    return item;
                })
                .collect(Collectors.toList());

        // 5. 返回结果
        HomeKhxzdjzbqkRespVO respVO = new HomeKhxzdjzbqkRespVO();
        respVO.setList(list);
        respVO.setTotal(records.size());
        return respVO;
    }

    //拜访人均分布情况
    @Override
    public HomeKhxzdjzbqkRespVO getHomeInfoBfrjfbqk(HomeReqVO reqVO) {
        //1.先查出所有的拜访记录
        InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
        infoPageReqVO.setPageSize(-1);
        infoPageReqVO.setVisitDate(reqVO.getSearchTime());
        infoPageReqVO.setCompanyName(reqVO.getCompanyName());
        PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
        List<InfoDO> records = infoDOPageResult.getList();
        // 按业务员分组计数
        Map<String, Long> countMap = records.stream()
                .filter(r -> StringUtils.isNotBlank(r.getCreator()))
                .collect(Collectors.groupingBy(InfoDO::getCreator, Collectors.counting()));

        // 倒序排序，取前10
        List<Map.Entry<String, Long>> top10 = countMap.entrySet().stream()
                .sorted(Map.Entry.<String, Long>comparingByValue())
                .limit(10)
                .collect(Collectors.toList());

        // 拆分为两个数组
//        List<String> names = top10.stream().map(Map.Entry::getKey).collect(Collectors.toList());
//        List<Integer> values = top10.stream().map(e -> e.getValue().intValue()).collect(Collectors.toList());
        //直接成对放入
        List<HomeKhxzdjzbqkRespVO.TypeCountItem> list = top10.stream()
                .map(entry -> {
                    HomeKhxzdjzbqkRespVO.TypeCountItem item = new HomeKhxzdjzbqkRespVO.TypeCountItem();
                    item.setName(entry.getKey());
                    item.setValue(entry.getValue().intValue());
                    return item;
                })
                .collect(Collectors.toList());
        HomeKhxzdjzbqkRespVO respVO = new HomeKhxzdjzbqkRespVO();
        respVO.setList(list);
        return respVO;
    }

    // 客户拜访方式分布情况
    @Override
    public HomeKhxzdjzbqkRespVO getHomeInfoKhbffszbqk(HomeReqVO reqVO) {
        //1.先查出所有的客户信息
        InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
        infoPageReqVO.setPageSize(-1);
        infoPageReqVO.setVisitDate(reqVO.getSearchTime());
        infoPageReqVO.setCompanyName(reqVO.getCompanyName());
        PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
        List<InfoDO> records = infoDOPageResult.getList();

        // 2.分组计数：Map<customerType字典值, 数量>
        Map<Integer, Long> typeCountMap = records.stream()
                .filter(info -> info.getVisitMethod() != null) // ✅ null 保护
                .collect(Collectors.groupingBy(InfoDO::getVisitMethod, Collectors.counting()));

        // 3. 加载字典并转换为 Map
        List<DictDataRespDTO> dictList = dictDataApi.getDictDataList("visit_method");
        Map<String, String> dictMap = dictList.stream()
                .collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel));

        // 4. 组装返回列表
        List<HomeKhxzdjzbqkRespVO.TypeCountItem> list = typeCountMap.entrySet().stream()
                .map(entry -> {
                    HomeKhxzdjzbqkRespVO.TypeCountItem item = new HomeKhxzdjzbqkRespVO.TypeCountItem();
                    item.setName(dictMap.getOrDefault(entry.getKey().toString(), "未知"));
                    item.setValue(entry.getValue().intValue());
                    return item;
                })
                .collect(Collectors.toList());

        // 5. 返回结果
        HomeKhxzdjzbqkRespVO respVO = new HomeKhxzdjzbqkRespVO();
        respVO.setList(list);
        respVO.setTotal(records.size());
        return respVO;
    }

    //  客户部门分布情况
    @Override
    public HomeKhxzdjzbqkRespVO getHomeInfoKhbmzbqk(HomeReqVO reqVO) {
        //1.先查出所有的客户信息
        InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
        infoPageReqVO.setPageSize(-1);
        infoPageReqVO.setVisitDate(reqVO.getSearchTime());
        infoPageReqVO.setCompanyName(reqVO.getCompanyName());
        PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
        List<InfoDO> records = infoDOPageResult.getList();

        // 2.分组计数：Map<customerType字典值, 数量>
        Map<String, Long> typeCountMap = records.stream()
                .filter(record -> record.getDepartment() != null)
                .collect(Collectors.groupingBy(InfoDO::getDepartment, Collectors.counting()));

        // 3. 加载字典并转换为 Map
        List<DictDataRespDTO> dictList = dictDataApi.getDictDataList("customer_dept");
        Map<String, String> dictMap = dictList.stream()
                .collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel));

        // 4. 组装返回列表
        List<HomeKhxzdjzbqkRespVO.TypeCountItem> list = typeCountMap.entrySet().stream()
                .map(entry -> {
                    HomeKhxzdjzbqkRespVO.TypeCountItem item = new HomeKhxzdjzbqkRespVO.TypeCountItem();
                    item.setName(dictMap.getOrDefault(entry.getKey().toString(), "未知"));
                    item.setValue(entry.getValue().intValue());
                    return item;
                })
                .collect(Collectors.toList());

        // 5. 返回结果
        HomeKhxzdjzbqkRespVO respVO = new HomeKhxzdjzbqkRespVO();
        respVO.setList(list);
        respVO.setTotal(records.size());
        return respVO;
    }

    //  客户拜访类型分布情况
    @Override
    public HomeKhxzdjzbqkRespVO getHomeInfoKhbflxzbqk(HomeReqVO reqVO) {
        //1.先查出所有的客户信息
        InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
        infoPageReqVO.setPageSize(-1);
        infoPageReqVO.setVisitDate(reqVO.getSearchTime());
        infoPageReqVO.setCompanyName(reqVO.getCompanyName());
        PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
        List<InfoDO> records = infoDOPageResult.getList();

        // 2.分组计数：Map<customerType字典值, 数量>
        Map<Integer, Long> typeCountMap = records.stream()
                .filter(info -> info.getVisitType() != null) // ✅ null 保护
                .collect(Collectors.groupingBy(InfoDO::getVisitType, Collectors.counting()));

        // 3. 加载字典并转换为 Map
        List<DictDataRespDTO> dictList = dictDataApi.getDictDataList("visit_type");
        Map<String, String> dictMap = dictList.stream()
                .collect(Collectors.toMap(DictDataRespDTO::getValue, DictDataRespDTO::getLabel));

        // 4. 组装返回列表
        List<HomeKhxzdjzbqkRespVO.TypeCountItem> list = typeCountMap.entrySet().stream()
                .map(entry -> {
                    HomeKhxzdjzbqkRespVO.TypeCountItem item = new HomeKhxzdjzbqkRespVO.TypeCountItem();
                    item.setName(dictMap.getOrDefault(entry.getKey().toString(), "未知"));
                    item.setValue(entry.getValue().intValue());
                    return item;
                })
                .collect(Collectors.toList());

        // 5. 返回结果
        HomeKhxzdjzbqkRespVO respVO = new HomeKhxzdjzbqkRespVO();
        respVO.setList(list);
        respVO.setTotal(records.size());
        return respVO;
    }

    @Override
    public HomeKhxzdjzbqkRespVO getHomeInfoBfcplxzbqk(HomeReqVO reqVO) {
        //1.先查出所有的客户信息
        InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
        infoPageReqVO.setPageSize(-1);
        infoPageReqVO.setVisitDate(reqVO.getSearchTime());
        infoPageReqVO.setCompanyName(reqVO.getCompanyName());
        PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
        List<InfoDO> records = infoDOPageResult.getList();
        // 2. 收集所有产品 ID
        Set<Long> productIdSet = records.stream()
                .flatMap(r -> {
                    String ids = r.getVisitProductIds();
                    if (StringUtils.isBlank(ids)) return Stream.empty();
                    return Arrays.stream(ids.split(","))
                            .map(String::trim)
                            .filter(StringUtils::isNotBlank)
                            .map(Long::valueOf);
                })
                .collect(Collectors.toSet());

        // 3. 查询产品信息（id => 名称-规格）
        //判断是否为空
        if (CollUtil.isEmpty(productIdSet)){
            HomeKhxzdjzbqkRespVO vo = new HomeKhxzdjzbqkRespVO();
            vo.setList(new ArrayList<HomeKhxzdjzbqkRespVO.TypeCountItem>());
            return vo;
        }
        List<ProductDO> productList = productMapper.selectByIds(productIdSet);
        Map<Long, String> productMap = productList.stream()
                .collect(Collectors.toMap(
                        ProductDO::getId,
                        p -> p.getProductName() + "-" + p.getSpecification()
                ));

        // 4. 遍历所有拜访记录统计产品使用次数
        Map<String, Integer> statMap = new HashMap<>();
        for (InfoDO record : records) {
            if (StringUtils.isBlank(record.getVisitProductIds())) continue;
            for (String pidStr : record.getVisitProductIds().split(",")) {
                Long pid = NumberUtils.toLong(pidStr.trim(), -1);
                if (!productMap.containsKey(pid)) continue;
                String key = productMap.get(pid);
                statMap.merge(key, 1, Integer::sum);
            }
        }

        // 5. 排序取前 N（如 top10）
        List<Map.Entry<String, Integer>> topList = statMap.entrySet().stream()
                .sorted(Map.Entry.<String, Integer>comparingByValue())
                .limit(10)
                .collect(Collectors.toList());

        //直接成对放入list
        List<HomeKhxzdjzbqkRespVO.TypeCountItem> list = topList.stream()
                .map(entry -> {
                    HomeKhxzdjzbqkRespVO.TypeCountItem item = new HomeKhxzdjzbqkRespVO.TypeCountItem();
                    item.setName(entry.getKey());
                    item.setValue(entry.getValue());
                    return item;
                })
                .collect(Collectors.toList());
//        List<String> names = topList.stream().map(Map.Entry::getKey).collect(Collectors.toList());
//        List<Integer> values = topList.stream().map(Map.Entry::getValue).collect(Collectors.toList());

        // 6. 构建返回结果
        HomeKhxzdjzbqkRespVO vo = new HomeKhxzdjzbqkRespVO();
        vo.setList(list);
        return vo;
    }

    @Override
    public HomeBfrtjRespVO getHomeInfoBfrtj(HomeReqVO reqVO) {
        //1.先查出所有的客户信息
        InfoPageReqVO infoPageReqVO = new InfoPageReqVO();
        infoPageReqVO.setPageSize(-1);
        infoPageReqVO.setVisitDate(reqVO.getSearchTime());
        infoPageReqVO.setCompanyName(reqVO.getCompanyName());
        PageResult<InfoDO> infoDOPageResult = infoMapper.selectHomePage(infoPageReqVO);
        List<InfoDO> records = infoDOPageResult.getList();
        // 2. 按日期（yyyy-MM-dd）分组计数
        Map<LocalDate, Long> dateCountMap = records.stream()
                .collect(Collectors.groupingBy(
                        r -> r.getVisitDate().toLocalDate(),
                        Collectors.counting()
                ));

        // 3. 排序（从晚到早）+ 限制最多31天
        List<Map.Entry<LocalDate, Long>> sorted = dateCountMap.entrySet().stream()
                .sorted(Map.Entry.<LocalDate, Long>comparingByKey().reversed())
                .limit(31)
                .sorted(Map.Entry.comparingByKey()) // 前端从左到右看，从早到晚排列
                .collect(Collectors.toList());

        // 4. 构造 VO
        List<String> dates = sorted.stream()
                .map(e -> formatDate(e.getKey())) // 4月01日
                .collect(Collectors.toList());
        List<Integer> counts = sorted.stream()
                .map(e -> e.getValue().intValue())
                .collect(Collectors.toList());

        HomeBfrtjRespVO vo = new HomeBfrtjRespVO();
        vo.setDates(dates);
        vo.setCounts(counts);
        return vo;
    }

    // 工具方法：格式化为 4月01日
    private String formatDate(LocalDate date) {
        return date.getMonthValue() + "月" + String.format("%02d", date.getDayOfMonth()) + "日";
    }
}