package com.jeesharp.business.modules.food.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.jeesharp.business.modules.food.entity.FoodMealMenu;
import com.jeesharp.business.modules.food.mapper.FoodMealMenuMapper;
import com.jeesharp.business.modules.food.service.FoodMealMenuService;
import com.jeesharp.business.modules.food.vo.FoodMealMenuQueryVO;
import com.jeesharp.framework.exception.BizErrorException;
import com.jeesharp.framework.mybatis.core.service.CrudService;
import com.jeesharp.framework.utils.WebFrameworkUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;

@Service
@Transactional(readOnly = true)
public class FoodMealMenuServiceImpl extends CrudService<FoodMealMenuMapper, FoodMealMenu, FoodMealMenuQueryVO> implements FoodMealMenuService {

    private static final int DEFAULT_SORT_NO = 0;
    private static final String IDS_SEPARATOR = ",";
    private static final String MENU_NOT_FOUND_MESSAGE = "菜单不存在";
    private static final String DEL_NORMAL = "0";
    private static final String MENU_STATUS_PUBLISHED = "published";

    @Override
    @Transactional(readOnly = false)
    public void createMenu(FoodMealMenu entity) {
        if (entity.getSortNo() == null) {
            entity.setSortNo(DEFAULT_SORT_NO);
        }
        save(entity);
    }

    @Override
    @Transactional(readOnly = false)
    public void updateMenu(FoodMealMenu entity) {
        if (StrUtil.isBlank(entity.getId()) || get(entity.getId()) == null) {
            throw new BizErrorException(MENU_NOT_FOUND_MESSAGE);
        }
        if (entity.getSortNo() == null) {
            entity.setSortNo(DEFAULT_SORT_NO);
        }
        update(entity);
    }

    @Override
    @Transactional(readOnly = false)
    public void updatePublishStatus(String id, String publishStatus) {
        FoodMealMenu current = get(id);
        if (current == null) {
            throw new BizErrorException(MENU_NOT_FOUND_MESSAGE);
        }
        LocalDateTime publishTime = MENU_STATUS_PUBLISHED.equals(publishStatus) ? LocalDateTime.now() : null;
        int updated = getBaseMapper().updatePublishStatus(id, publishStatus, publishTime, WebFrameworkUtils.getLoginUserTenantCode());
        if (updated != 1) {
            throw new BizErrorException(MENU_NOT_FOUND_MESSAGE);
        }
    }

    @Override
    public boolean existsSameScope(String id, String serviceAreaId, LocalDate menuDate, String mealType, String scopeType, String companyId) {
        return getBaseMapper().countSameScope(id, serviceAreaId, menuDate, mealType, scopeType, companyId == null ? "" : companyId) > 0;
    }

    @Override
    public FoodMealMenu getSameScope(String serviceAreaId, LocalDate menuDate, String mealType, String scopeType, String companyId) {
        return getBaseMapper().selectSameScope(serviceAreaId, menuDate, mealType, scopeType, companyId == null ? "" : companyId);
    }

    @Override
    public List<String> listIdsBySameScope(String serviceAreaId, LocalDate menuDate, String mealType, String scopeType, String companyId) {
        return getBaseMapper().selectIdsBySameScope(serviceAreaId, menuDate, mealType, scopeType, companyId == null ? "" : companyId);
    }

    @Override
    public List<FoodMealMenu> listPublishedMenus(String serviceAreaId, LocalDate mealDate, String mealType, Set<String> scopeTypes, Set<String> mealTypeCandidates) {
        LambdaQueryWrapper<FoodMealMenu> wrapper = new LambdaQueryWrapper<FoodMealMenu>()
            .eq(FoodMealMenu::getPublishStatus, MENU_STATUS_PUBLISHED)
            .eq(FoodMealMenu::getDelFlag, DEL_NORMAL)
            .in(FoodMealMenu::getScopeType, scopeTypes)
            .orderByAsc(FoodMealMenu::getMenuDate)
            .orderByAsc(FoodMealMenu::getSortNo);
        if (StrUtil.isNotBlank(serviceAreaId)) {
            wrapper.and(w -> w
                .eq(FoodMealMenu::getServiceAreaId, serviceAreaId)
                .or()
                .eq(FoodMealMenu::getRestaurantId, serviceAreaId)
            );
        }
        if (mealDate != null) {
            wrapper.eq(FoodMealMenu::getMenuDate, mealDate);
        }
        if (StrUtil.isNotBlank(mealType)) {
            wrapper.in(FoodMealMenu::getMealType, mealTypeCandidates);
        }
        return getBaseMapper().selectList(wrapper);
    }

    @Override
    public List<FoodMealMenu> listByIds(List<String> ids) {
        if (ids == null || ids.isEmpty()) {
            return Collections.emptyList();
        }
        return getBaseMapper().selectByIds(ids.stream().filter(StrUtil::isNotBlank).distinct().toList());
    }

    @Override
    public List<FoodMealMenu> listByDateRange(LocalDate startDate, LocalDate endDate, List<String> serviceAreaIds) {
        LambdaQueryWrapper<FoodMealMenu> wrapper = new LambdaQueryWrapper<FoodMealMenu>()
            .eq(FoodMealMenu::getDelFlag, DEL_NORMAL)
            .ge(FoodMealMenu::getMenuDate, startDate)
            .le(FoodMealMenu::getMenuDate, endDate)
            .orderByAsc(FoodMealMenu::getMenuDate)
            .orderByAsc(FoodMealMenu::getSortNo);
        if (serviceAreaIds != null && !serviceAreaIds.isEmpty()) {
            wrapper.in(FoodMealMenu::getServiceAreaId, serviceAreaIds);
        }
        return getBaseMapper().selectList(wrapper);
    }
}
