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

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.ChineseDate;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.excel.ElderlyBirthdayExcelVO;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.BirthdayCareDO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyInfoDO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyPhotoDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.BirthdayCareMapper;
import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyInfoMapper;
import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyPhotoMapper;
import cn.iocoder.yudao.module.system.enums.common.BooleanEnum;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.validation.annotation.Validated;

import java.time.LocalDate;
import java.time.Period;
import java.time.YearMonth;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 长者生日关怀 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
public class BirthdayCareServiceImpl implements BirthdayCareService {


    @Resource
    private BuildService buildService;

    @Resource
    private ElderlyInfoMapper elderlyInfoMapper;

    @Resource
    private BirthdayCareMapper birthdayCareMapper;

    @Resource
    private ElderlyPhotoMapper elderlyPhotoMapper;


    @Override
    public Long createBirthdayCare(BirthdayCareDO birthdayCare) {
        birthdayCare.setCreatedTime(new Date());
        birthdayCare.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
        birthdayCareMapper.insert(birthdayCare);


        ElderlyPhotoDO elderlyPhotoDO = new ElderlyPhotoDO();
        elderlyPhotoDO.setCreatedTime(new Date());
        elderlyPhotoDO.setShootingTime(new Date());
        elderlyPhotoDO.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
        elderlyPhotoDO.setType(1); //生日类型的
        elderlyPhotoDO.setImages(birthdayCare.getPictures());
        elderlyPhotoDO.setElderId(birthdayCare.getElderId());
        elderlyPhotoMapper.insert(elderlyPhotoDO);
        return birthdayCare.getId();
    }

    @Override
    public List<ElderlyInfoDO> getElderBirthdayListByDate(String monthStr, Integer orgType, Long[] tenantIds) {
        YearMonth yearMonth = YearMonth.parse(monthStr, DateTimeFormatter.ofPattern("yyyy-MM"));
        LocalDate firstDayOfMonth = yearMonth.atDay(1);
        LocalDate lastDayOfMonth = yearMonth.atEndOfMonth();
        int targetMonth = yearMonth.getMonthValue();

        // 根据月份查询过生日的长者列表
        // 公历生日：birthday 字段是完整日期（带年份），不能用 2026-01-01~2026-01-31 去 between。
        // 这里先按条件查出公历生日不为空的长者，再用 Java 过滤 month。
        //（如需走数据库函数过滤，可在 Mapper 自定义 SQL，用 MONTH(birthday)=? 等方式，兼容性需结合数据库类型确认）
        List<ElderlyInfoDO> gregorianCalendarElderList = elderlyInfoMapper.selectList(new LambdaQueryWrapperX<ElderlyInfoDO>()
                .eqIfPresent(ElderlyInfoDO::getOrgType, orgType)
                .inIfPresent(ElderlyInfoDO::getTenantId, tenantIds)
                .isNotNull(ElderlyInfoDO::getBirthday)
                .and(e->e.eq(ElderlyInfoDO::getIsLunarCalendar, BooleanEnum.FALSE.getValue())
                        .or().isNull(ElderlyInfoDO::getIsLunarCalendar)));

        gregorianCalendarElderList = gregorianCalendarElderList.stream()
                .filter(e -> {
                    Date birthday = e.getBirthday();
                    if (birthday == null) {
                        return false;
                    }
                    LocalDate birthdayDate = birthday.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                    return birthdayDate.getMonthValue() == targetMonth;
                })
                .collect(Collectors.toList());

        //农历生日
        List<ElderlyInfoDO> chineseCalendarElderList = elderlyInfoMapper.selectList(new LambdaQueryWrapperX<ElderlyInfoDO>()
                .eq(ElderlyInfoDO::getIsLunarCalendar, BooleanEnum.TRUE.getValue())
                .eqIfPresent(ElderlyInfoDO::getOrgType, orgType)
                .inIfPresent(ElderlyInfoDO::getTenantId, tenantIds)
                .isNotNull(ElderlyInfoDO::getChineseCalendar));

        for (ElderlyInfoDO elderlyInfoDO : chineseCalendarElderList) {
            String chineseCalendar = elderlyInfoDO.getChineseCalendar();
            String[] split = chineseCalendar.replaceAll("(?<=^|-)0+", "").split("-");

            ChineseDate chineseDate = new ChineseDate(yearMonth.getYear(), Integer.parseInt(split[0]), Integer.parseInt(split[1]));
            //公历日期
            LocalDate localDate = chineseDate.getGregorianDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            elderlyInfoDO.setBirthdayCareDate(localDate);
        }
        //过滤范围
        List<ElderlyInfoDO> collect = chineseCalendarElderList.stream()
                .filter(e -> !e.getBirthdayCareDate().isBefore(firstDayOfMonth))
                .filter(e -> !e.getBirthdayCareDate().isAfter(lastDayOfMonth)).collect(Collectors.toList());


        List<ElderlyInfoDO> elderlyInfoList = new ArrayList<>();
        elderlyInfoList.addAll(collect);
        elderlyInfoList.addAll(gregorianCalendarElderList);

        for (ElderlyInfoDO elderlyInfoDO : elderlyInfoList) {
            elderlyInfoDO.setBedName(buildService.getFullBedName(elderlyInfoDO.getId()));
            Date birthday = elderlyInfoDO.getBirthday();

            if (birthday != null) {
                LocalDate birthdayDate = birthday.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                Period age = Period.between(birthdayDate, LocalDate.now());
                elderlyInfoDO.setElderAge(age.getYears());
            }
        }
        return elderlyInfoList;
    }

    @Override
    public List<ElderlyBirthdayExcelVO> getElderBirthdayExportList(String monthStr, Integer orgType, Long[] tenantIds) {
        List<ElderlyInfoDO> list = getElderBirthdayListByDate(monthStr, orgType, tenantIds);

        // 生日只展示 MM-dd
        DateTimeFormatter mmddFormatter = DateTimeFormatter.ofPattern("MM-dd");

        List<ElderlyBirthdayExcelVO> excelList = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            ElderlyInfoDO elder = list.get(i);
            ElderlyBirthdayExcelVO vo = new ElderlyBirthdayExcelVO();
            vo.setSeq(i + 1);
            vo.setName(elder.getElderName());
            vo.setGender(elder.getElderSex() != null && elder.getElderSex() == 1 ? "男" : (elder.getElderSex() != null && elder.getElderSex() == 2 ? "女" : ""));
            vo.setAge(elder.getElderAge());
            vo.setBedName(elder.getBedName());

            Date birthday = elder.getBirthday();
            if (birthday != null) {
                LocalDate birthdayDate = birthday.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                vo.setBirthday(mmddFormatter.format(birthdayDate));
            } else {
                vo.setBirthday("");
            }

            // 这里按现有字段优先输出“护理级别名称”，若后续有“风险等级”字段可在此拼接
            vo.setNurseLevelOrRiskLevel(elder.getNurseLevelName());
            excelList.add(vo);
        }
        return excelList;
    }

    @Override
    public BirthdayCareDO getBirthdayCare(Long elderId) {
        List<BirthdayCareDO> birthdayCareList = birthdayCareMapper.selectList(new LambdaQueryWrapperX<BirthdayCareDO>()
                .eq(BirthdayCareDO::getElderId, elderId)
                .orderByDesc(BirthdayCareDO::getCreatedTime)
        );
        if (CollectionUtil.isNotEmpty(birthdayCareList)) {
            BirthdayCareDO birthdayCareDO = birthdayCareList.stream().findFirst().get();
            birthdayCareDO.setElderlyInfo(elderlyInfoMapper.selectById(elderId));
            return birthdayCareDO;
        }
        return null;
    }

    @Override
    public void updateBirthdayCare(BirthdayCareDO updateReqVO) {
        birthdayCareMapper.updateById(updateReqVO);
    }

    @Override
    public List<String> getBirthdayPictures(Long elderId) {
        List<BirthdayCareDO> birthdayCareList = birthdayCareMapper.selectList(new LambdaQueryWrapperX<BirthdayCareDO>()
                .eq(BirthdayCareDO::getElderId, elderId));
        return birthdayCareList.stream().map(BirthdayCareDO::getPictures).collect(Collectors.toList());
    }
}