package cn.iocoder.yudao.module.system.service.nursing;

import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.module.system.controller.admin.nursing.vo.SpecialNursingPlanItemExecuteReqVO;
import cn.iocoder.yudao.module.system.controller.admin.nursing.vo.SpecialNursingPlanItemRespVO;
import cn.iocoder.yudao.module.system.controller.admin.nursing.vo.SpecialNursingPlanItemUnfinishedByFloorRespVO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlySpecialNursingLogDO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlySpecialNursingPlanDO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlySpecialNursingPlanItemDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlySpecialNursingLogMapper;
import cn.iocoder.yudao.module.system.dal.mysql.biz.SpecialNursingPlanItemMapper;
import cn.iocoder.yudao.module.system.dal.mysql.biz.SpecialNursingPlanMapper;
import cn.iocoder.yudao.module.system.service.biz.BuildService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

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

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.COMMON_NOT_FOUND;

@Service
@Validated
public class SpecialNursingPlanItemServiceImpl implements SpecialNursingPlanItemService {

    @Resource
    private SpecialNursingPlanItemMapper specialNursingPlanItemMapper;
    @Resource
    private ElderlySpecialNursingLogMapper elderlySpecialNursingLogMapper;
    @Resource
    private BuildService buildService;
    @Resource
    private SpecialNursingPlanMapper specialNursingPlanMapper;

    @Autowired
    private ElderlyInfoMapper elderlyInfoMapper;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void executePlan(SpecialNursingPlanItemExecuteReqVO executeReqVO) {
        ElderlySpecialNursingPlanItemDO specialItem = specialNursingPlanItemMapper.selectById(executeReqVO.getSpecialPlanItemId());
        if (specialItem == null) {
            throw exception(COMMON_NOT_FOUND);
        }
        specialItem.setStatus(1);
        specialNursingPlanItemMapper.updateById(specialItem);

        ElderlySpecialNursingLogDO logDO = new ElderlySpecialNursingLogDO();
        logDO.setSpecialPlanItemId(executeReqVO.getSpecialPlanItemId());
        logDO.setElderId(executeReqVO.getElderId());
        logDO.setFinishTime(executeReqVO.getFinishTime());
        logDO.setRemark(executeReqVO.getRemark());
        logDO.setImageUrl(executeReqVO.getImageUrl());
        logDO.setTenantId(executeReqVO.getTenantId() != null ? executeReqVO.getTenantId() : specialItem.getTenantId());
        elderlySpecialNursingLogMapper.insert(logDO);
    }

    @Override
    public List<SpecialNursingPlanItemUnfinishedByFloorRespVO> getUnfinishedByFloorId(Long floorId) {
        List<ElderlyInfoDO> elderlyInfoDOS = elderlyInfoMapper.selectList(new LambdaQueryWrapperX<ElderlyInfoDO>()
                .eq(ElderlyInfoDO::getFloorId, floorId)
                .eq(ElderlyInfoDO::getInStatus, 1));
//        List<BuildRoomInfoVO> rooms = buildService.getElderListByFloorId(floorId);
//        if (CollectionUtil.isEmpty(rooms)) {
//            return Collections.emptyList();
//        }
//
//        Map<Long, String> elderNameById = new LinkedHashMap<>();
//        for (BuildRoomInfoVO room : rooms) {
//            List<BuildBedInfoVO> bedList = room.getBedList();
//            if (CollectionUtil.isEmpty(bedList)) {
//                continue;
//            }
//            for (BuildBedInfoVO bed : bedList) {
//                if (bed.getElderId() == null) {
//                    continue;
//                }
//                elderNameById.putIfAbsent(bed.getElderId(), bed.getElderName());
//            }
//        }
//
//        if (elderNameById.isEmpty()) {
//            return Collections.emptyList();
//        }
        Map<Long, String> elderNameById = elderlyInfoDOS.stream().collect(Collectors.toMap(ElderlyInfoDO::getId, ElderlyInfoDO::getElderName));
        List<Long> elderIds = new ArrayList<>(elderNameById.keySet());
        if(CollectionUtil.isEmpty(elderIds)){
            return Collections.emptyList();
        }
        List<ElderlySpecialNursingPlanDO> plans = specialNursingPlanMapper.selectList(
                new LambdaQueryWrapperX<ElderlySpecialNursingPlanDO>()
                        .in(ElderlySpecialNursingPlanDO::getElderId, elderIds)
        );
        if (CollectionUtil.isEmpty(plans)) {
            return Collections.emptyList();
        }

        Map<Long, String> fallbackElderNameById = plans.stream()
                .filter(p -> p.getElderId() != null)
                .collect(Collectors.toMap(ElderlySpecialNursingPlanDO::getElderId, ElderlySpecialNursingPlanDO::getElderName, (a, b) -> a));

        Map<Long, List<Long>> planIdsByElderId = plans.stream()
                .filter(p -> p.getElderId() != null && p.getId() != null)
                .collect(Collectors.groupingBy(ElderlySpecialNursingPlanDO::getElderId,
                        Collectors.mapping(ElderlySpecialNursingPlanDO::getId, Collectors.toList())));

        List<Long> planIds = plans.stream()
                .map(ElderlySpecialNursingPlanDO::getId)
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        if (CollectionUtil.isEmpty(planIds)) {
            return Collections.emptyList();
        }

        List<ElderlySpecialNursingPlanItemDO> unfinishedItems = specialNursingPlanItemMapper.selectList(
                new LambdaQueryWrapperX<ElderlySpecialNursingPlanItemDO>()
                        .in(ElderlySpecialNursingPlanItemDO::getSpecialNursingPlanId, planIds)
                        .eq(ElderlySpecialNursingPlanItemDO::getStatus, 0)
                        .orderByAsc(ElderlySpecialNursingPlanItemDO::getId)
        );
        if (CollectionUtil.isEmpty(unfinishedItems)) {
            return Collections.emptyList();
        }

        Map<Long, List<ElderlySpecialNursingPlanItemDO>> itemsByPlanId = unfinishedItems.stream()
                .collect(Collectors.groupingBy(ElderlySpecialNursingPlanItemDO::getSpecialNursingPlanId));

        List<SpecialNursingPlanItemUnfinishedByFloorRespVO> result = new ArrayList<>();
        for (Map.Entry<Long, List<Long>> entry : planIdsByElderId.entrySet()) {
            Long elderId = entry.getKey();
            List<Long> elderPlanIds = entry.getValue();
            if (CollectionUtil.isEmpty(elderPlanIds)) {
                continue;
            }

            List<ElderlySpecialNursingPlanItemDO> elderItems = new ArrayList<>();
            for (Long planId : elderPlanIds) {
                List<ElderlySpecialNursingPlanItemDO> planItems = itemsByPlanId.get(planId);
                if (CollectionUtil.isEmpty(planItems)) {
                    continue;
                }
                elderItems.addAll(planItems);
            }
            if (CollectionUtil.isEmpty(elderItems)) {
                continue;
            }

            String elderName = elderNameById.get(elderId);
            if (StringUtils.isBlank(elderName)) {
                elderName = fallbackElderNameById.get(elderId);
            }

            SpecialNursingPlanItemUnfinishedByFloorRespVO respVO = new SpecialNursingPlanItemUnfinishedByFloorRespVO();
            respVO.setElderName(elderName);
            respVO.setElderId(elderId);
            respVO.setSpecialItem(BeanUtils.toBean(elderItems, SpecialNursingPlanItemRespVO.class));
            result.add(respVO);
        }

        return result;
    }
}
