package com.jeesharp.business.modules.food.application.api;

import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.finance.api.dto.PaySettleBizOrderSnapshot;
import com.jeesharp.business.modules.food.entity.FoodBookingOrder;
import com.jeesharp.business.modules.food.entity.FoodMealOrder;
import com.jeesharp.business.modules.food.entity.FoodRestaurant;
import com.jeesharp.business.modules.food.service.FoodBookingOrderService;
import com.jeesharp.business.modules.food.service.FoodMealOrderService;
import com.jeesharp.business.modules.food.service.FoodRestaurantService;
import com.jeesharp.business.modules.food.api.FoodFinanceReadApi;
import com.jeesharp.business.modules.food.vo.FoodBookingOrderQueryVO;
import com.jeesharp.business.modules.food.vo.FoodBookingResultVO;
import com.jeesharp.business.modules.food.vo.FoodMealOrderQueryVO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * {@link FoodFinanceReadApi} 实现，集中美食各子业态的财务只读查询（Application 层 api 包）。
 *
 * @author jeesharp
 * @since 2026-06-11
 */
@Service
@AllArgsConstructor
public class FoodFinanceReadApiImpl implements FoodFinanceReadApi {

    private static final String ORDER_TYPE_PERSONAL = "personal";
    private static final String ORDER_TYPE_COMPANY = "company";

    private final FoodBookingOrderService foodBookingOrderService;
    private final FoodRestaurantService foodRestaurantService;
    private final FoodMealOrderService foodMealOrderService;

    @Override
    public PaySettleBizOrderSnapshot getFoodBookingSnapshot(String bizOrderId) {
        if (StrUtil.isBlank(bizOrderId)) {
            return null;
        }
        FoodBookingOrder order = foodBookingOrderService.get(bizOrderId.trim());
        return order == null ? null : toFoodBookingSnapshot(order);
    }

    @Override
    public PaySettleBizOrderSnapshot getPersonalMealSnapshot(String bizOrderId) {
        return getMealSnapshot(bizOrderId, ORDER_TYPE_PERSONAL);
    }

    @Override
    public PaySettleBizOrderSnapshot getCompanyMealSnapshot(String bizOrderId) {
        return getMealSnapshot(bizOrderId, ORDER_TYPE_COMPANY);
    }

    @Override
    public String findFoodBookingOrderIdByOrderNo(String orderNo) {
        if (StrUtil.isBlank(orderNo)) {
            return null;
        }
        FoodBookingOrderQueryVO query = new FoodBookingOrderQueryVO();
        query.setTradeOrderId(orderNo.trim());
        List<FoodBookingOrder> list = foodBookingOrderService.findList(query);
        return list == null || list.isEmpty() ? null : list.get(0).getId();
    }

    @Override
    public String findPersonalMealOrderIdByOrderNo(String orderNo) {
        return findMealOrderIdByOrderNo(orderNo, ORDER_TYPE_PERSONAL);
    }

    @Override
    public String findCompanyMealOrderIdByOrderNo(String orderNo) {
        return findMealOrderIdByOrderNo(orderNo, ORDER_TYPE_COMPANY);
    }

    @Override
    public Map<String, String> mapFoodBookingOrderNoByIds(Collection<String> bizOrderIds) {
        if (bizOrderIds == null || bizOrderIds.isEmpty()) {
            return Collections.emptyMap();
        }
        Map<String, String> map = new HashMap<>();
        for (String id : bizOrderIds) {
            if (StrUtil.isBlank(id)) {
                continue;
            }
            FoodBookingOrder order = foodBookingOrderService.get(id.trim());
            if (order != null && StrUtil.isNotBlank(order.getTradeOrderId())) {
                map.put(order.getId(), order.getTradeOrderId());
            }
        }
        return map;
    }

    @Override
    public Map<String, String> mapPersonalMealOrderNoByIds(Collection<String> bizOrderIds) {
        return mapMealOrderNoByIds(bizOrderIds, ORDER_TYPE_PERSONAL);
    }

    @Override
    public Map<String, String> mapCompanyMealOrderNoByIds(Collection<String> bizOrderIds) {
        return mapMealOrderNoByIds(bizOrderIds, ORDER_TYPE_COMPANY);
    }

    private PaySettleBizOrderSnapshot getMealSnapshot(String bizOrderId, String orderType) {
        if (StrUtil.isBlank(bizOrderId)) {
            return null;
        }
        FoodMealOrder order = foodMealOrderService.get(bizOrderId.trim());
        if (order == null || !orderType.equals(order.getOrderType())) {
            return null;
        }
        return toMealSnapshot(order);
    }

    private String findMealOrderIdByOrderNo(String orderNo, String orderType) {
        if (StrUtil.isBlank(orderNo)) {
            return null;
        }
        FoodMealOrder byTrade = foodMealOrderService.lockByTradeOrderId(orderNo.trim());
        if (byTrade != null && orderType.equals(byTrade.getOrderType())) {
            return byTrade.getId();
        }
        FoodMealOrderQueryVO query = new FoodMealOrderQueryVO();
        query.setOrderNo(orderNo.trim());
        query.setOrderType(orderType);
        List<FoodMealOrder> list = foodMealOrderService.findList(query);
        return list == null || list.isEmpty() ? null : list.get(0).getId();
    }

    private Map<String, String> mapMealOrderNoByIds(Collection<String> bizOrderIds, String orderType) {
        if (bizOrderIds == null || bizOrderIds.isEmpty()) {
            return Collections.emptyMap();
        }
        Map<String, String> map = new HashMap<>();
        for (String id : bizOrderIds) {
            if (StrUtil.isBlank(id)) {
                continue;
            }
            FoodMealOrder order = foodMealOrderService.get(id.trim());
            if (order != null && orderType.equals(order.getOrderType())
                    && StrUtil.isNotBlank(order.getOrderNo())) {
                map.put(order.getId(), order.getOrderNo());
            }
        }
        return map;
    }

    private PaySettleBizOrderSnapshot toFoodBookingSnapshot(FoodBookingOrder order) {
        PaySettleBizOrderSnapshot snapshot = new PaySettleBizOrderSnapshot();
        snapshot.setBizOrderId(order.getId());
        snapshot.setOrderNo(order.getTradeOrderId());
        snapshot.setPayBatchId(order.getId());
        FoodRestaurant restaurant = StrUtil.isBlank(order.getRestaurantId())
                ? null : foodRestaurantService.get(order.getRestaurantId());
        if (restaurant != null && StrUtil.isNotBlank(restaurant.getTenantId())) {
            snapshot.setTenantId(restaurant.getTenantId());
        } else if (StrUtil.isNotBlank(order.getTenantId())) {
            snapshot.setTenantId(order.getTenantId());
        }
        BigDecimal payAmount = resolveFoodBookingPayAmount(order);
        snapshot.setPayAmount(payAmount);
        snapshot.setTotalAmount(payAmount);
        return snapshot;
    }

    private PaySettleBizOrderSnapshot toMealSnapshot(FoodMealOrder order) {
        PaySettleBizOrderSnapshot snapshot = new PaySettleBizOrderSnapshot();
        snapshot.setBizOrderId(order.getId());
        snapshot.setOrderNo(order.getOrderNo());
        snapshot.setPayBatchId(order.getId());
        snapshot.setTenantId(order.getTenantId());
        BigDecimal payAmount = resolveMealPayAmount(order);
        snapshot.setPayAmount(payAmount);
        snapshot.setTotalAmount(payAmount);
        return snapshot;
    }

    private BigDecimal resolveFoodBookingPayAmount(FoodBookingOrder order) {
        FoodBookingResultVO vo = foodBookingOrderService.getBookingResult(order.getId());
        if (vo != null && vo.getAmount() != null && vo.getAmount().compareTo(BigDecimal.ZERO) > 0) {
            return vo.getAmount();
        }
        return BigDecimal.ZERO;
    }

    private BigDecimal resolveMealPayAmount(FoodMealOrder order) {
        if (order.getUserPayAmount() != null && order.getUserPayAmount().compareTo(BigDecimal.ZERO) > 0) {
            return order.getUserPayAmount().setScale(2, RoundingMode.HALF_UP);
        }
        return BigDecimal.ZERO;
    }
}
