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.FoodMealOrder;
import com.jeesharp.business.modules.food.mapper.FoodMealOrderMapper;
import com.jeesharp.business.modules.food.service.FoodMealOrderService;
import com.jeesharp.business.modules.food.vo.FoodMealOrderQueryVO;
import com.jeesharp.framework.mybatis.core.service.CrudService;
import com.jeesharp.framework.pojo.Page;
import com.jeesharp.framework.utils.WebFrameworkUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * 订餐订单领域服务：个人/企业订餐单持久化与悲观锁查询（支付、退款并发控制）。
 *
 * <p>业务编排见 {@link com.jeesharp.business.modules.food.application.FoodPersonalMealApplicationService}
 * 与 {@link com.jeesharp.business.modules.food.application.FoodCompanyMealApplicationService}。</p>
 *
 * @author jeesharp
 * @since 2026-06-07
 */
@Service
@Transactional(readOnly = true)
public class FoodMealOrderServiceImpl extends CrudService<FoodMealOrderMapper, FoodMealOrder, FoodMealOrderQueryVO> implements FoodMealOrderService {

    private static final String DEL_NORMAL = "0";

    @Override
    public FoodMealOrder lockById(String id, String tenantCode) {
        return getBaseMapper().selectByIdForUpdate(id, tenantCode);
    }

    @Override
    public FoodMealOrder lockByTradeOrderId(String tradeOrderId) {
        return getBaseMapper().selectByTradeOrderIdForUpdate(tradeOrderId);
    }

    @Override
    public FoodMealOrder lockByUnifiedOrderId(String unifiedOrderId) {
        return getBaseMapper().selectByUnifiedOrderIdForUpdate(unifiedOrderId);
    }

    @Override
    public FoodMealOrder lockByTradeCenterOrderId(String tradeCenterOrderId) {
        return getBaseMapper().selectByTradeCenterOrderIdForUpdate(tradeCenterOrderId);
    }

    @Override
    public List<FoodMealOrder> listActiveByMemberIdAndMenuId(String memberId, String menuId, List<String> orderStatuses) {
        return getBaseMapper().selectList(new LambdaQueryWrapper<FoodMealOrder>()
            .select(FoodMealOrder::getId)
            .eq(FoodMealOrder::getMemberId, memberId)
            .eq(FoodMealOrder::getMenuId, menuId)
            .in(FoodMealOrder::getOrderStatus, orderStatuses)
            .eq(FoodMealOrder::getDelFlag, DEL_NORMAL));
    }

    @Override
    public Page<FoodMealOrder> findOrderPage(Page<FoodMealOrder> page, FoodMealOrderQueryVO query) {
        FoodMealOrderQueryVO q = query != null ? query : new FoodMealOrderQueryVO();
        LambdaQueryWrapper<FoodMealOrder> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(FoodMealOrder::getDelFlag, DEL_NORMAL);
        String tenantCode = WebFrameworkUtils.getLoginUserTenantCode();
        if (StrUtil.isNotBlank(tenantCode)) {
            wrapper.apply(
                "EXISTS (SELECT 1 FROM biz_food_meal_service_area sa WHERE sa.id = IFNULL(service_area_id, restaurant_id) COLLATE utf8mb4_general_ci AND sa.del_flag = '0' AND (sa.tenant_code = {0} OR sa.tenant_code IS NULL))",
                tenantCode
            );
        }
        if (StrUtil.isNotBlank(q.getOrderNo())) {
            wrapper.eq(FoodMealOrder::getOrderNo, q.getOrderNo().trim());
        }
        if (StrUtil.isNotBlank(q.getOrderType())) {
            wrapper.eq(FoodMealOrder::getOrderType, q.getOrderType().trim());
        }
        if (StrUtil.isNotBlank(q.getRestaurantId())) {
            wrapper.eq(FoodMealOrder::getRestaurantId, q.getRestaurantId().trim());
        }
        if (StrUtil.isNotBlank(q.getServiceAreaId())) {
            wrapper.eq(FoodMealOrder::getServiceAreaId, q.getServiceAreaId().trim());
        }
        if (StrUtil.isNotBlank(q.getMenuId())) {
            wrapper.eq(FoodMealOrder::getMenuId, q.getMenuId().trim());
        }
        if (q.getMenuDate() != null) {
            wrapper.eq(FoodMealOrder::getMenuDate, q.getMenuDate());
        }
        if (StrUtil.isNotBlank(q.getMealType())) {
            wrapper.eq(FoodMealOrder::getMealType, q.getMealType().trim());
        }
        if (StrUtil.isNotBlank(q.getMemberId())) {
            wrapper.eq(FoodMealOrder::getMemberId, q.getMemberId().trim());
        }
        if (StrUtil.isNotBlank(q.getCompanyId())) {
            wrapper.eq(FoodMealOrder::getCompanyId, q.getCompanyId().trim());
        }
        if (StrUtil.isNotBlank(q.getOrderStatus())) {
            wrapper.eq(FoodMealOrder::getOrderStatus, q.getOrderStatus().trim());
        }
        if (StrUtil.isNotBlank(q.getPayStatus())) {
            wrapper.eq(FoodMealOrder::getPayStatus, q.getPayStatus().trim());
        }
        wrapper.orderByDesc(FoodMealOrder::getCreateDate);
        page.setPageNo(q.getPageNo());
        page.setPageSize(q.getPageSize());
        page.setCurrent(q.getPageNo());
        page.setSize(q.getPageSize());
        return (Page<FoodMealOrder>) getBaseMapper().selectPage(page, wrapper);
    }

    @Override
    @Transactional(readOnly = false)
    public void insertOrder(FoodMealOrder order) {
        order.setIsNewRecord(true);
        order.preInsert();
        getBaseMapper().insert(order);
    }

    @Override
    @Transactional(readOnly = false)
    public void updateOrder(FoodMealOrder order) {
        order.preUpdate();
        getBaseMapper().updateById(order);
    }
}
