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

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.controller.admin.elderly.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
import cn.iocoder.yudao.module.system.dal.dataobject.elderly.ElderlyNursingLogDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
import cn.iocoder.yudao.module.system.dal.mysql.elderly.ElderlyNursingLogMapper;
import cn.iocoder.yudao.module.system.service.biz.BuildService;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Validated
public class ElderlyNursingLogServiceImpl implements ElderlyNursingLogService {

    @Resource
    private ElderlyNursingLogMapper nursingLogMapper;
    @Resource
    private ElderlyInfoMapper elderlyInfoMapper;
    @Resource
    private BuildService buildService;

    @Override
    public Boolean create(List<ElderlyNursingLogSaveReqVO> createReqVO) {
        List<ElderlyNursingLogDO> insertList = new ArrayList<>();
        for (ElderlyNursingLogSaveReqVO reqVO : createReqVO) {
            ElderlyNursingLogDO nursingLog = BeanUtils.toBean(reqVO, ElderlyNursingLogDO.class);
            nursingLog.setStatus(1);
            insertList.add(nursingLog);
        }
        return nursingLogMapper.insertBatch(insertList);
    }

    @Override
    public void executeNursingLog(ElderlyNursingLogSaveReqVO updateReqVO) {
        ElderlyNursingLogDO nursingLog = BeanUtils.toBean(updateReqVO, ElderlyNursingLogDO.class);
        nursingLog.setStatus(1);
        nursingLogMapper.updateById(nursingLog);
    }

    @Override
    public void delete(Long id) {
        nursingLogMapper.deleteById(id);
    }

    @Override
    public ElderlyNursingLogRespVO get(Long id) {
        ElderlyNursingLogDO nursingLog = nursingLogMapper.selectById(id);
        if (nursingLog == null) {
            return null;
        }
        ElderlyNursingLogRespVO respVO = BeanUtils.toBean(nursingLog, ElderlyNursingLogRespVO.class);
        fillElderInfo(Collections.singletonList(respVO));
        return respVO;
    }

    @Override
    public PageResult<ElderlyNursingLogSimpleRespVO> getPage(ElderlyNursingLogPageReqVO pageReqVO) {
        // 如果按长者姓名搜索，先获取符合条件的 elderIds
        List<Long> elderIds = null;
        if (pageReqVO.getElderName() != null && !pageReqVO.getElderName().trim().isEmpty()) {
            List<ElderlyInfoDO> elders = elderlyInfoMapper.selectList(new LambdaQueryWrapperX<ElderlyInfoDO>()
                    .like(ElderlyInfoDO::getElderName, pageReqVO.getElderName()));
            elderIds = elders.stream().map(ElderlyInfoDO::getId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
            if (elderIds.isEmpty()) {
                return PageResult.empty();
            }
        }

        // 在 SQL 层面加入 elderIds 过滤，确保分页正确
        PageResult<ElderlyNursingLogDO> pageResult = nursingLogMapper.selectPage(pageReqVO,
                new LambdaQueryWrapperX<ElderlyNursingLogDO>()
                        .inIfPresent(ElderlyNursingLogDO::getElderId, elderIds)
                        .groupBy(ElderlyNursingLogDO::getElderId)
                        .orderByDesc(ElderlyNursingLogDO::getFinishTime)
                        .orderByDesc(ElderlyNursingLogDO::getId));

        List<ElderlyNursingLogDO> list = pageResult.getList();
        if (CollectionUtil.isEmpty(list)) {
            return PageResult.empty();
        }

        // 批量获取 ElderlyInfoDO 用于填充护理等级
        Set<Long> elderIdSet = list.stream().map(ElderlyNursingLogDO::getElderId).filter(Objects::nonNull).collect(Collectors.toSet());
        final Map<Long, ElderlyInfoDO> elderMap;
        if (!elderIdSet.isEmpty()) {
            List<ElderlyInfoDO> elders = elderlyInfoMapper.selectBatchIds(elderIdSet);
            elderMap = elders.stream().collect(Collectors.toMap(ElderlyInfoDO::getId, Function.identity(), (a, b) -> a));
        } else {
            elderMap = Collections.emptyMap();
        }

        // 转换为简化 VO
        List<ElderlyNursingLogSimpleRespVO> simpleVOList = list.stream().map(nursingLog -> {
            ElderlyNursingLogSimpleRespVO simpleVO = new ElderlyNursingLogSimpleRespVO();
            ElderlyInfoDO elder = elderMap.get(nursingLog.getElderId());
            if (elder != null) {
                simpleVO.setElderId(nursingLog.getElderId());
                simpleVO.setElderName(elder.getElderName());
                simpleVO.setNurseLevelName(elder.getNurseLevelName());
                simpleVO.setBedName(buildService.getFullBedName(elder.getId()));
            }
            return simpleVO;
        }).collect(Collectors.toList());

        return new PageResult<>(simpleVOList, pageResult.getTotal());
    }

    @Override
    public List<ElderlyNursingLogRespVO> getList(ElderlyNursingLogListReqVO listReqVO) {
        // 查询护理记录列表（关联护理项目名称）
        List<ElderlyNursingLogRespVO> voList = nursingLogMapper.getFinishList(
                listReqVO.getNurse(),
                listReqVO.getElderName(),
                listReqVO.getTenantId(),
                listReqVO.getFrequencyCategoryType(),
                listReqVO.getStartDate().atStartOfDay(),
                listReqVO.getEndDate().plusDays(1).atStartOfDay());

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

        // 填充老人信息（护理等级、床位等）
        fillElderInfo(voList);

        return voList;
    }

    @Override
    public ElderlyNursingLogDetailRespVO getDetailByElderId(Long elderId, LocalDate start, LocalDate end, Integer pageNo, Integer pageSize) {
        if (elderId == null) {
            return null;
        }
        ElderlyInfoDO elder = elderlyInfoMapper.selectById(elderId);
        if (elder == null) {
            return null;
        }
        Page<ElderlyNursingLogRespVO> page = new Page<>(
                pageNo == null ? 1 : pageNo,
                pageSize == null ? 10 : pageSize
        );
        List<ElderlyNursingLogRespVO> records = nursingLogMapper.selectPageByElderIdWithItemName(page,
                elderId,
                start == null ? null : start.atStartOfDay(),
                end == null ? null : end.plusDays(1).atStartOfDay());

        ElderlyNursingLogDetailRespVO detailRespVO = new ElderlyNursingLogDetailRespVO();
        ElderlyNursingLogDetailRespVO.Header header = new ElderlyNursingLogDetailRespVO.Header();
        header.setElderName(elder.getElderName());
        header.setBedName(buildService.getFullBedName(elderId));
        header.setNurseLevelName(elder.getNurseLevelName());
        detailRespVO.setHeader(header);

        for (ElderlyNursingLogRespVO record : records) {
            record.setElderName(elder.getElderName());
            record.setBedName(header.getBedName());
            record.setNurseLevelName(elder.getNurseLevelName());
        }
        detailRespVO.setRecords(new PageResult<>(records, page.getTotal()));
        return detailRespVO;
    }

    private void fillElderInfo(List<ElderlyNursingLogRespVO> list) {
        if (CollectionUtil.isEmpty(list)) {
            return;
        }
        Set<Long> elderIds = list.stream().map(ElderlyNursingLogRespVO::getElderId)
                .filter(Objects::nonNull).collect(Collectors.toSet());
        if (CollectionUtil.isEmpty(elderIds)) {
            return;
        }
        List<ElderlyInfoDO> elders = elderlyInfoMapper.selectBatchIds(elderIds);
        Map<Long, ElderlyInfoDO> elderMap = elders.stream().filter(e -> e.getId() != null)
                .collect(Collectors.toMap(ElderlyInfoDO::getId, Function.identity(), (a, b) -> a));

        for (ElderlyNursingLogRespVO vo : list) {
            ElderlyInfoDO elder = elderMap.get(vo.getElderId());
            if (elder != null) {
                vo.setElderName(elder.getElderName());
                vo.setNurseLevelName(elder.getNurseLevelName());
            }
            vo.setBedName(buildService.getFullBedName(vo.getElderId()));
        }
    }
}
