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

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
import cn.iocoder.yudao.module.system.controller.admin.biz.vo.*;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.ElderlyOrderFoodDO;
import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.CateringPlanDO;
import cn.iocoder.yudao.module.system.dal.dataobject.restaurant.CateringPlanItemDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.ElderlyOrderFoodMapper;
import cn.iocoder.yudao.module.system.dal.mysql.restaurant.CateringPlanItemMapper;
import cn.iocoder.yudao.module.system.dal.mysql.restaurant.CateringPlanMapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import kotlin.jvm.internal.Lambda;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;

import java.lang.reflect.Field;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

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

@Service
@Validated
public class ElderlyOrderFoodServiceImpl implements ElderlyOrderFoodService {

    @Resource
    private ElderlyOrderFoodMapper elderlyOrderFoodMapper;

    @Autowired
    private CateringPlanMapper cateringPlanMapper;

    @Autowired
    private CateringPlanItemMapper cateringPlanItemMapper;

    @Override
    public String create(List<ElderlyOrderFoodCommitVO> voList) {
        Map<Long, List<ElderlyOrderFoodCommitVO>> map = voList.stream()
                .collect(Collectors.groupingBy(ElderlyOrderFoodCommitVO::getElderId));
        for (Long elderId : map.keySet()) {
            ElderlyOrderFoodCommitVO firstItem = map.get(elderId).get(0);
            LocalDate orderFoodDate = firstItem.getOrderFoodDate();
            LocalDate monday = orderFoodDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
            LocalDate sunday = orderFoodDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
            elderlyOrderFoodMapper.delete(new LambdaQueryWrapperX<ElderlyOrderFoodDO>()
                    .eq(ElderlyOrderFoodDO::getElderId, elderId)
                    .eq(ElderlyOrderFoodDO::getTenantId, firstItem.getTenantId())
                    .between(ElderlyOrderFoodDO::getOrderFoodDate, monday, sunday));
        }
        List<ElderlyOrderFoodDO> insertList = voList.stream()
                .map(vo -> {
                    ElderlyOrderFoodDO doObj = new ElderlyOrderFoodDO();
                    BeanUtils.copyProperties(vo, doObj);
                    return doObj;
                })
                .collect(Collectors.toList());
        elderlyOrderFoodMapper.insertBatch(insertList);
        return "success";
    }

    @Override
    public void update(ElderlyOrderFoodDO updateReqVO) {
        validateExists(updateReqVO.getId());
        elderlyOrderFoodMapper.updateById(updateReqVO);
    }

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

    @Override
    public List<ElderlyOrderFoodGetResVO> get(ElderlyOrderFoodGetReqVO reqVO) {
        // 获取当前日期
        LocalDate now = LocalDate.now();
        // 周五要拿到下周一的菜单
        if (now.getDayOfWeek().getValue() >= 5) {
            now = now.plusDays(3);
        }
        // 本周一（第一天）
        LocalDate monday = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        // 本周日（最后一天）
        LocalDate sunday = now.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
        CateringPlanDO cateringPlanDO = cateringPlanMapper.selectOne(new LambdaQueryWrapperX<CateringPlanDO>()
                .eq(CateringPlanDO::getRestaurantId, 27)
                .eq(CateringPlanDO::getScheduledStartDate,monday)
                .eq(CateringPlanDO::getScheduledEndDate,sunday));
        if(cateringPlanDO == null){
            throw exceptionCustomMsg(COMMON_ERROR,"暂无菜单，请联系后勤配菜单计划！");
        }
        List<CateringPlanItemDO> cateringPlanItemDOS = cateringPlanItemMapper.selectList(new LambdaQueryWrapperX<CateringPlanItemDO>()
                .eq(CateringPlanItemDO::getCateringPlanId, cateringPlanDO.getId())
                .in(CateringPlanItemDO::getMealTimes, "早餐", "中餐", "晚餐"));

        // 将餐次映射到对象
        Map<String, CateringPlanItemDO> itemMap = cateringPlanItemDOS.stream()
                .collect(Collectors.toMap(CateringPlanItemDO::getMealTimes, Function.identity()));

        List<ElderlyOrderFoodGetResVO> week = new ArrayList<>();
        LocalDate current = monday;
        while (!current.isAfter(sunday)) {
            String dayOfWeek = current.getDayOfWeek().name().toLowerCase(); // monday, tuesday...
            ElderlyOrderFoodGetResVO daily = new ElderlyOrderFoodGetResVO();
            daily.setElderId(reqVO.getElderId());
            daily.setDate(current);
            daily.setDayOfWeek(current.getDayOfWeek().toString()); // 如 MONDAY

            // 早餐
            CateringPlanItemDO breakfast = itemMap.get("早餐");
            if (breakfast != null) {
                daily.setBreakfastFixed(getFieldValue(breakfast, dayOfWeek));
                daily.setBreakfastOptional(getFieldValue(breakfast, dayOfWeek + "Extra"));
            }

            // 午餐
            CateringPlanItemDO lunch = itemMap.get("中餐");
            if (lunch != null) {
                daily.setLunchFixed(getFieldValue(lunch, dayOfWeek));
                daily.setLunchOptional(getFieldValue(lunch, dayOfWeek + "Extra"));
            }

            // 晚餐
            CateringPlanItemDO dinner = itemMap.get("晚餐");
            if (dinner != null) {
                daily.setDinnerFixed(getFieldValue(dinner, dayOfWeek));
                daily.setDinnerOptional(getFieldValue(dinner, dayOfWeek + "Extra"));
            }

            week.add(daily);
            current = current.plusDays(1);
        }

        // 5. 查询长者本周报餐记录
        List<ElderlyOrderFoodDO> orders = elderlyOrderFoodMapper.selectList(
                new LambdaQueryWrapper<ElderlyOrderFoodDO>()
                        .eq(ElderlyOrderFoodDO::getElderId, reqVO.getElderId())
                        .between(ElderlyOrderFoodDO::getOrderFoodDate, monday, sunday)
        );
        Map<LocalDate, ElderlyOrderFoodDO> orderMap = orders.stream()
                .collect(Collectors.toMap(ElderlyOrderFoodDO::getOrderFoodDate, Function.identity()));

        // 将报餐信息合并到每日计划
        for (ElderlyOrderFoodGetResVO daily : week) {
            ElderlyOrderFoodDO order = orderMap.get(daily.getDate());
            if (order != null) {
                daily.setSelectedExtra(order.getExtraDishes());
                daily.setSelectedExtraOption(order.getExtraDishesOption());
            }
        }
        return week;
    }

    @Override
    public PageResult<ElderlyOrderFoodRespVO> getPage(ElderlyOrderFoodPageReqVO pageReqVO) {
        Page<ElderlyOrderFoodRespVO> page =  new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        List<ElderlyOrderFoodRespVO> data = elderlyOrderFoodMapper.selectPageWithDetail(page, pageReqVO);
        return new PageResult<>(data, page.getTotal());
    }

    @Override
    public List<ElderOrderFoodExportExcelVO> getList(ElderlyOrderFoodPageReqVO reqVO) {
        List<ElderOrderFoodExportExcelVO> list = elderlyOrderFoodMapper.getList(reqVO);
        Map<LocalDate, Map<String, Long>> collect = list.stream()
                .filter(vo -> vo.getExtraDishes() != null && !vo.getExtraDishes().trim().isEmpty())
                .collect(Collectors.groupingBy(
                        ElderOrderFoodExportExcelVO::getOrderFoodDate,
                        Collectors.groupingBy(
                                ElderOrderFoodExportExcelVO::getExtraDishes,
                                Collectors.counting()
                        )
                ));
        for (Map.Entry<LocalDate, Map<String, Long>> localDateEntry : collect.entrySet()) {
            for (Map.Entry<String, Long> countEntry : localDateEntry.getValue().entrySet()) {
                ElderOrderFoodExportExcelVO value = new ElderOrderFoodExportExcelVO();
                value.setElderName("总计");
                value.setOrderFoodDate(localDateEntry.getKey());
                value.setExtraDishes(countEntry.getKey() + ":" + countEntry.getValue());
                list.add(value);
            }
        }
        return list;
    }

    private void validateExists(Long id) {
        if (id == null || elderlyOrderFoodMapper.selectById(id) == null) {
            throw exception(COMMON_NOT_FOUND);
        }
    }

    // 反射获取字段值（生产环境建议用缓存或字段名映射）
    private String getFieldValue(CateringPlanItemDO item, String fieldName) {
        try {
            Field field = CateringPlanItemDO.class.getDeclaredField(fieldName);
            field.setAccessible(true);
            return (String) field.get(item);
        } catch (Exception e) {
            // 字段可能不存在（如周六的 Extra 可能没配），返回空
            return null;
        }
    }
}

