package com.ruoyi.app.mendian;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.annotation.Anonymous;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.system.domain.FoodSpecs;
import com.ruoyi.system.domain.FoodSpecsValue;
import com.ruoyi.system.service.IFoodSpecsService;
import com.ruoyi.system.service.IFoodSpecsValueService;
import com.ruoyi.system.service.MerchantStoreAccessService;
import com.ruoyi.system.utils.Auth;
import com.ruoyi.system.utils.AuthContext;
import com.ruoyi.system.utils.JwtUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品规格管理 Controller（规格组 + 级联规格值）
 * 门店级可复用规格模板
 *
 * @author ruoyi
 * @date 2026-07-15
 */
@RestController
@RequestMapping("/chanting/foodSpec")
public class FoodSpecController extends BaseController
{
    @Autowired
    private IFoodSpecsService foodSpecsService;

    @Autowired
    private IFoodSpecsValueService foodSpecsValueService;
    @Autowired
    private MerchantStoreAccessService merchantStoreAccessService;
    /**
     * 规格组分页列表（每条带 foodSpecsItems）
     */
    @Anonymous
    @Auth(session = true)
    @GetMapping("/foodSpecPageList")
    public AjaxResult foodSpecPageList(@RequestHeader String token,
                                       @RequestParam(defaultValue = "1") Integer pageNum,
                                       @RequestParam(defaultValue = "10") Integer pageSize,
                                       @RequestParam Long mdId,
                                       @RequestParam(required = false) String language) {
        merchantStoreAccessService.requireStoreAccess(
                AuthContext.requireUserId(), mdId);
        Page<FoodSpecs> page = new Page<>(pageNum, pageSize);
        LambdaQueryWrapper<FoodSpecs> qw = new LambdaQueryWrapper<>();
        qw.eq(FoodSpecs::getMdId, mdId);
        qw.eq(FoodSpecs::getIsDelete, false);
        if (language != null && !"".equals(language)) {
            qw.eq(FoodSpecs::getLanguage, language);
        }
        qw.orderByAsc(FoodSpecs::getSort).orderByDesc(FoodSpecs::getId);
        IPage<FoodSpecs> result = foodSpecsService.page(page, qw);
        fillItems(result.getRecords(), false);
        return success(result);
    }



    /**
     * 保存规格组（含级联规格值）：id<=0 新增，否则更新
     */
    @Anonymous
    @Auth(session = true)
    @PostMapping("/saveFoodSpec")
    @Transactional(rollbackFor = Exception.class)
    public AjaxResult saveFoodSpec(@RequestHeader String token, @RequestBody List<FoodSpecs> list) {
        if (list == null || list.isEmpty()) {
            return error();
        }
        Long userId = AuthContext.requireUserId();
        for (FoodSpecs s : list) {
            if (s.getId() == null || s.getId() <= 0) {
                merchantStoreAccessService.requireStoreAccess(userId, s.getMdId());
            } else {
                FoodSpecs existing = requireSpecsAccess(userId, s.getId());
                s.setMdId(existing.getMdId());
            }
            if (s.getIsDelete() == null) {
                s.setIsDelete(false);
            }
            if (s.getIsOpen() == null) {
                s.setIsOpen(true);
            }
            saveOrUpdateSpecs(s);
            // 级联规格值（全量替换：先删前端未保留的，再保存/新增）
            if (s.getObjects() != null) {
                removeDeletedValues(s);
                for (FoodSpecsValue v : s.getObjects()) {
                    v.setParentId(s.getId());
                    if (v.getIsOpen() == null) {
                        v.setIsOpen(true);
                    }
                    saveOrUpdateValue(v);
                }
            }
        }
        return success();
    }

    private void saveOrUpdateSpecs(FoodSpecs s) {
        if (s.getId() == null || s.getId() <= 0) {
            s.setId(null);
            foodSpecsService.save(s);
        } else {
            foodSpecsService.updateById(s);
        }
    }

    private void saveOrUpdateValue(FoodSpecsValue v) {
        if (v.getId() == null || v.getId() <= 0) {
            v.setId(null);
            foodSpecsValueService.save(v);
        } else {
            foodSpecsValueService.updateById(v);
        }
    }

    /**
     * 规格值全量替换：删除该规格组下 DB 有、但前端 objects 未传（id>0 集合外）的规格值（物理删除）。
     * 仅对已存在规格组（id>0）生效；新增规格组无历史数据，无需 diff。
     */
    private void removeDeletedValues(FoodSpecs s) {
        if (s.getId() == null || s.getId() <= 0) {
            return;
        }
        // 前端保留的规格值 id（id>0 的；id<=0 是新增，不参与 diff）
        List<Long> keepIds = s.getObjects().stream()
                .map(FoodSpecsValue::getId)
                .filter(id -> id != null && id > 0)
                .collect(Collectors.toList());
        // DB 中该规格组的全部规格值 id
        List<Long> dbIds = foodSpecsValueService.list(
                new LambdaQueryWrapper<FoodSpecsValue>()
                        .eq(FoodSpecsValue::getParentId, s.getId())
                        .select(FoodSpecsValue::getId)
        ).stream().map(FoodSpecsValue::getId).collect(Collectors.toList());
        // DB 有但前端没传 → 物理删除
        List<Long> toRemove = dbIds.stream()
                .filter(id -> !keepIds.contains(id))
                .collect(Collectors.toList());
        if (!toRemove.isEmpty()) {
            foodSpecsValueService.removeByIds(toRemove);
        }
    }

    /**
     * 规格详情（带全部规格值）
     */
    @Anonymous
    @Auth(session = true)
    @GetMapping("/getSpecs")
    public AjaxResult getSpecs(@RequestHeader String token, @RequestParam Long id) {
        requireSpecsAccess(AuthContext.requireUserId(), id);
        FoodSpecs s = foodSpecsService.getById(id);
        if (s != null) {
            List<FoodSpecs> list = new ArrayList<>();
            list.add(s);
            fillItems(list, false);
        }
        return success(s);
    }

    /**
     * 软删除规格组（is_delete=1）
     */
    @Anonymous
    @Auth(session = true)
    @GetMapping("/deleteFoodSpec")
    public AjaxResult deleteFoodSpec(@RequestHeader String token, @RequestParam Long id) {
        requireSpecsAccess(AuthContext.requireUserId(), id);
        FoodSpecs s = new FoodSpecs();
        s.setId(id);
        s.setIsDelete(true);
        return toAjax(foodSpecsService.updateById(s));
    }

    /**
     * 商品编辑页：本门店可用规格（is_open=1 & is_delete=0，仅含 is_open=1 的规格值）
     */
    @Anonymous
    @Auth(session = true)
    @GetMapping("/getAvailableSpecsList")
    public AjaxResult getAvailableSpecsList(@RequestHeader String token, @RequestParam Long mdId,
                                            @RequestParam(required = false) String language) {
        merchantStoreAccessService.requireStoreAccess(
                AuthContext.requireUserId(), mdId);
        LambdaQueryWrapper<FoodSpecs> qw = new LambdaQueryWrapper<>();
        qw.eq(FoodSpecs::getMdId, mdId);
        qw.eq(FoodSpecs::getIsOpen, true);
        qw.eq(FoodSpecs::getIsDelete, false);
        if (language != null && !"".equals(language)) {
            qw.eq(FoodSpecs::getLanguage, language);
        }
        qw.orderByAsc(FoodSpecs::getSort).orderByDesc(FoodSpecs::getId);
        List<FoodSpecs> list = foodSpecsService.list(qw);
        fillItems(list, true);
        return success(list);
    }

    /**
     * 启停规格组
     */
    @Anonymous
    @Auth(session = true)
    @GetMapping("/changeOpen")
    public AjaxResult changeOpen(@RequestHeader String token,
                                 @RequestParam Long id, @RequestParam Boolean isOpen) {
        requireSpecsAccess(AuthContext.requireUserId(), id);
        FoodSpecs s = new FoodSpecs();
        s.setId(id);
        s.setIsOpen(isOpen);
        return toAjax(foodSpecsService.updateById(s));
    }

    /**
     * 启停规格值
     */
    @Anonymous
    @Auth(session = true)
    @GetMapping("/changeSpecValueOpen")
    public AjaxResult changeSpecValueOpen(@RequestHeader String token,
                                          @RequestParam Long id, @RequestParam Boolean isOpen) {
        Long userId = AuthContext.requireUserId();
        FoodSpecsValue existingValue = foodSpecsValueService.getById(id);
        if (existingValue == null) {
            return error();
        }
        requireSpecsAccess(userId, existingValue.getParentId());
        FoodSpecsValue v = new FoodSpecsValue();
        v.setId(id);
        v.setIsOpen(isOpen);
        return toAjax(foodSpecsValueService.updateById(v));
    }

    private FoodSpecs requireSpecsAccess(Long userId, Long specsId) {
        FoodSpecs specs = foodSpecsService.getById(specsId);
        if (specs == null) {
            throw new com.ruoyi.common.exception.ServiceException(
                    com.ruoyi.common.utils.MessageUtils.message("merchant.store.access.denied"));
        }
        merchantStoreAccessService.requireStoreAccess(userId, specs.getMdId());
        return specs;
    }

    /**
     * 批量填充规格值到规格组（避免 N+1）
     *
     * @param onlyOpen true=只取 is_open=1 的规格值（用于商品可用规格）
     */
    private void fillItems(List<FoodSpecs> list, boolean onlyOpen) {
        if (list == null || list.isEmpty()) {
            return;
        }
        List<Long> ids = list.stream().map(FoodSpecs::getId).collect(Collectors.toList());
        LambdaQueryWrapper<FoodSpecsValue> qw = new LambdaQueryWrapper<FoodSpecsValue>()
                .in(FoodSpecsValue::getParentId, ids)
                .orderByAsc(FoodSpecsValue::getId);
        if (onlyOpen) {
            qw.eq(FoodSpecsValue::getIsOpen, true);
        }
        List<FoodSpecsValue> values = foodSpecsValueService.list(qw);
        Map<Long, List<FoodSpecsValue>> map = values.stream()
                .collect(Collectors.groupingBy(FoodSpecsValue::getParentId));
        for (FoodSpecs s : list) {
            s.setObjects(map.getOrDefault(s.getId(), new ArrayList<>()));
        }
    }
}
