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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.jeesharp.business.modules.common.support.QueryInCsvSupport;
import com.jeesharp.business.modules.food.convert.FoodDishConvert;
import com.jeesharp.business.modules.food.dto.FoodDishSaveDTO;
import com.jeesharp.business.modules.food.entity.FoodDish;
import com.jeesharp.business.modules.food.service.FoodDishService;
import com.jeesharp.business.modules.food.service.FoodRestaurantService;
import com.jeesharp.business.modules.food.vo.FoodDishInfoVO;
import com.jeesharp.business.modules.food.vo.FoodDishListVO;
import com.jeesharp.business.modules.food.vo.FoodDishQueryVO;
import com.jeesharp.framework.exception.BizErrorException;
import com.jeesharp.framework.pojo.Page;
import com.jeesharp.framework.pojo.query.PageRespVO;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Collections;
import java.util.List;
import java.util.Map;

@Service
@AllArgsConstructor
@Transactional(readOnly = true)
public class FoodDishApplicationService {

    private final FoodDishService foodDishService;
    private final FoodRestaurantService foodRestaurantService;

    public FoodDishInfoVO get(String id) {
        FoodDish entity = foodDishService.get(id);
        if (entity == null) {
            return null;
        }
        FoodDishInfoVO vo = FoodDishConvert.INSTANCE.toInfoVO(entity);
        enrichInfoDisplay(vo);
        return vo;
    }

    public PageRespVO<FoodDishListVO> findPage(Page<FoodDish> page, FoodDishQueryVO query) {
        FoodDishQueryVO prepared = prepareQuery(query);
        if (prepared == null) {
            return emptyPage(page);
        }
        Page<FoodDish> result = foodDishService.findPage(page, prepared);
        PageRespVO<FoodDishListVO> pageVo = FoodDishConvert.INSTANCE.toPageRespVO(result);
        enrichListDisplay(pageVo.getRecords());
        return pageVo;
    }

    @Transactional(readOnly = false)
    public void save(FoodDishSaveDTO dto) {
        validateSave(dto);
        FoodDish entity = FoodDishConvert.INSTANCE.toEntity(dto);
        if (StrUtil.isBlank(dto.getId())) {
            foodDishService.createDish(entity);
            return;
        }
        foodDishService.updateDish(entity);
    }

    @Transactional(readOnly = false)
    public void delete(String ids) {
        foodDishService.batchDelete(StrUtil.splitTrim(ids, ','));
    }

    @Transactional(readOnly = false)
    public void updateStatus(String id, Integer status) {
        validateStatus(status);
        foodDishService.updateStatus(id, status);
    }

    private void validateSave(FoodDishSaveDTO dto) {
        if (foodRestaurantService.get(dto.getRestaurantId()) == null) {
            throw new BizErrorException("所属门店不存在");
        }
        if (dto.getPrice() == null || dto.getPrice().compareTo(BigDecimal.ZERO) < 0) {
            throw new BizErrorException("菜品价格不能小于0");
        }
        dto.setImagesJson(normalizeJsonArray(dto.getImagesJson(), "菜品图片"));
        dto.setTagsJson(normalizeJsonArray(dto.getTagsJson(), "菜品标签"));
        validateStatus(dto.getStatus());
    }

    private String normalizeJsonArray(String value, String fieldName) {
        if (StrUtil.isBlank(value)) {
            return "[]";
        }
        try {
            return JSONUtil.parseArray(value).toString();
        } catch (Exception e) {
            throw new BizErrorException(fieldName + "格式不正确");
        }
    }

    private void validateStatus(Integer status) {
        if (status == null || (status != 0 && status != 1)) {
            throw new BizErrorException("状态值不正确");
        }
    }

    private FoodDishQueryVO prepareQuery(FoodDishQueryVO query) {
        FoodDishQueryVO q = query != null ? query : new FoodDishQueryVO();
        if (StrUtil.isNotBlank(q.getRestaurantName())) {
            List<String> restaurantIds = foodRestaurantService.findIdsByNameLike(q.getRestaurantName().trim());
            q.setRestaurantName(null);
            if (CollUtil.isEmpty(restaurantIds)) {
                return null;
            }
            q.setRestaurantIdInCsv(QueryInCsvSupport.toIdInCsv(restaurantIds));
        }
        return q;
    }

    private void enrichListDisplay(List<FoodDishListVO> rows) {
        if (CollUtil.isEmpty(rows)) {
            return;
        }
        List<String> restaurantIds = rows.stream()
                .map(FoodDishListVO::getRestaurantId)
                .filter(StrUtil::isNotBlank)
                .distinct()
                .toList();
        Map<String, String> restaurantNameMap = foodRestaurantService.mapRestaurantNameByIds(restaurantIds);
        for (FoodDishListVO row : rows) {
            if (StrUtil.isNotBlank(row.getRestaurantId())) {
                row.setRestaurantName(restaurantNameMap.get(row.getRestaurantId()));
            }
        }
    }

    private void enrichInfoDisplay(FoodDishInfoVO vo) {
        if (vo == null || StrUtil.isBlank(vo.getRestaurantId())) {
            return;
        }
        Map<String, String> nameMap = foodRestaurantService.mapRestaurantNameByIds(List.of(vo.getRestaurantId()));
        vo.setRestaurantName(nameMap.get(vo.getRestaurantId()));
    }

    private static PageRespVO<FoodDishListVO> emptyPage(Page<FoodDish> page) {
        PageRespVO<FoodDishListVO> empty = new PageRespVO<>();
        empty.setRecords(Collections.emptyList());
        empty.setTotal(0L);
        empty.setPageNo(page != null ? page.getPageNo() : 1L);
        empty.setPageSize(page != null ? page.getPageSize() : 10L);
        return empty;
    }
}
