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

import com.jeesharp.business.modules.common.enums.DisabledEnabledEnum;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.jeesharp.business.modules.mall.convert.MallProductTemplateConvert;
import com.jeesharp.business.modules.mall.dto.MallProductTemplateItemSaveDTO;
import com.jeesharp.business.modules.mall.dto.MallProductTemplateSaveDTO;
import com.jeesharp.business.modules.mall.entity.MallCategory;
import com.jeesharp.business.modules.mall.entity.MallProductTemplate;
import com.jeesharp.business.modules.mall.entity.MallProductTemplateItem;

import com.jeesharp.business.modules.mall.enums.MallProductTemplateAttrInputTypeEnum;
import com.jeesharp.business.modules.mall.enums.MallProductTemplateItemTypeEnum;
import com.jeesharp.business.modules.mall.service.MallCategoryService;
import com.jeesharp.business.modules.mall.service.MallProductTemplateItemService;
import com.jeesharp.business.modules.mall.service.MallProductTemplateService;
import com.jeesharp.business.modules.mall.vo.MallLinkedCategoryVO;
import com.jeesharp.business.modules.mall.vo.MallProductTemplateInfoVO;
import com.jeesharp.business.modules.mall.vo.MallProductTemplateItemVO;
import com.jeesharp.business.modules.mall.vo.MallProductTemplateListVO;
import com.jeesharp.business.modules.mall.vo.MallProductTemplateQueryVO;
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.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 商品发布模板应用服务：维护模板头、明细行，以及按类目解析模板（供 SPU 表单使用）。
 *
 * @author jeesharp
 * @since 2026-05-15
 */
@Service
@AllArgsConstructor
@Transactional(readOnly = true)
public class MallProductTemplateApplicationService {

    private final MallProductTemplateService mallProductTemplateService;
    private final MallProductTemplateItemService mallProductTemplateItemService;
    private final MallCategoryService mallCategoryService;

    public MallProductTemplateInfoVO get(String id) {
        MallProductTemplate entity = mallProductTemplateService.get(id);
        MallProductTemplateInfoVO vo = MallProductTemplateConvert.INSTANCE.toInfoVO(entity);
        vo.setItems(toItemVoList(mallProductTemplateItemService.listByTemplateId(id)));
        List<MallCategory> linked = mallCategoryService.listByTemplateId(id);
        if (CollUtil.isEmpty(linked)) {
            vo.setLinkedCategories(List.of());
        } else {
            vo.setLinkedCategories(
                linked.stream()
                    .map(c -> {
                        MallLinkedCategoryVO lc = new MallLinkedCategoryVO();
                        lc.setId(c.getId());
                        lc.setCategoryName(c.getCategoryName());
                        lc.setCategoryCode(c.getCategoryCode());
                        return lc;
                    })
                    .toList());
        }
        return vo;
    }

    /**
     * 按商品类目解析绑定的发布模板（含明细）；类目未绑定模板时返回 {@code null}。
     */
    public MallProductTemplateInfoVO resolveByCategoryId(String categoryId) {
        if (StrUtil.isBlank(categoryId)) {
            return null;
        }
        String templateId = mallCategoryService.resolveInheritedTemplateId(categoryId.trim());
        if (StrUtil.isBlank(templateId)) {
            return null;
        }
        return get(templateId);
    }

    public PageRespVO<MallProductTemplateListVO> findPage(Page<MallProductTemplate> page, MallProductTemplateQueryVO query) {
        Page<MallProductTemplate> result = mallProductTemplateService.findPage(page, query);
        PageRespVO<MallProductTemplateListVO> vo = MallProductTemplateConvert.INSTANCE.toPageRespVO(result);
        if (vo.getRecords() != null) {
            fillLinkedCategoryPaths(vo.getRecords());
        }
        return vo;
    }

    @Transactional(readOnly = false)
    public String save(MallProductTemplateSaveDTO dto) {
        validateItems(dto.getItems());
        MallProductTemplate entity = MallProductTemplateConvert.INSTANCE.toEntity(dto);
        if (entity.getStatus() == null) {
            entity.setStatus(DisabledEnabledEnum.ENABLED.getValue());
        }
        if (entity.getSortOrder() == null) {
            entity.setSortOrder(0);
        }
        boolean isNew = StrUtil.isBlank(dto.getId());
        if (isNew) {
            mallProductTemplateService.createTemplate(entity);
        } else {
            mallProductTemplateService.updateTemplate(entity);
        }
        String templateId = entity.getId();
        mallProductTemplateItemService.removeByTemplateId(templateId);
        List<MallProductTemplateItem> rows = buildItemEntities(dto.getItems(), templateId);
        mallProductTemplateItemService.batchInsert(rows);
        return templateId;
    }

    @Transactional(readOnly = false)
    public void delete(String ids) {
        for (String id : Arrays.asList(ids.split(","))) {
            if (StrUtil.isBlank(id)) {
                continue;
            }
            String tid = id.trim();
            mallProductTemplateItemService.removeByTemplateId(tid);
        }
        mallProductTemplateService.batchDelete(StrUtil.splitTrim(ids, ','));
    }

    private void validateItems(List<MallProductTemplateItemSaveDTO> items) {
        if (CollUtil.isEmpty(items)) {
            return;
        }
        int i = 0;
        for (MallProductTemplateItemSaveDTO row : items) {
            i++;
            if (row.getItemType() == null) {
                throw new IllegalArgumentException("第" + i + "行：行类型不能为空");
            }
            if (MallProductTemplateItemTypeEnum.SPEC.getValue().equals(row.getItemType())) {
                if (StrUtil.isBlank(row.getSpecId())) {
                    throw new IllegalArgumentException("第" + i + "行：规格维度须填写规格ID");
                }
            } else if (MallProductTemplateItemTypeEnum.ATTR.getValue().equals(row.getItemType())) {
                if (StrUtil.isBlank(row.getAttrKey())) {
                    throw new IllegalArgumentException("第" + i + "行：扩展属性须填写属性键");
                }
                if (StrUtil.isBlank(row.getAttrName())) {
                    throw new IllegalArgumentException("第" + i + "行：扩展属性须填写展示名称");
                }
                if (row.getInputType() == null) {
                    row.setInputType(MallProductTemplateAttrInputTypeEnum.TEXT.getValue());
                }
                if (MallProductTemplateAttrInputTypeEnum.fromValue(row.getInputType()) == null) {
                    throw new IllegalArgumentException("第" + i + "行：扩展属性录入方式无效");
                }
            } else {
                throw new IllegalArgumentException("第" + i + "行：未知行类型");
            }
        }
    }

    private List<MallProductTemplateItem> buildItemEntities(List<MallProductTemplateItemSaveDTO> items, String templateId) {
        if (CollUtil.isEmpty(items)) {
            return List.of();
        }
        List<MallProductTemplateItem> out = new ArrayList<>();
        for (MallProductTemplateItemSaveDTO s : items) {
            MallProductTemplateItem e = new MallProductTemplateItem();
            e.setTemplateId(templateId);
            e.setItemType(s.getItemType());
            e.setSpecId(s.getSpecId());
            e.setAttrKey(s.getAttrKey());
            e.setAttrName(s.getAttrName());
            e.setInputType(s.getInputType() != null ? s.getInputType() : MallProductTemplateAttrInputTypeEnum.TEXT.getValue());
            e.setOptionsJson(s.getOptionsJson());
            e.setRequiredFlag(Integer.valueOf(1).equals(s.getRequiredFlag()) ? 1 : 0);
            e.setSortOrder(s.getSortOrder() != null ? s.getSortOrder() : 0);
            out.add(e);
        }
        return out;
    }

    private List<MallProductTemplateItemVO> toItemVoList(List<MallProductTemplateItem> list) {
        if (CollUtil.isEmpty(list)) {
            return List.of();
        }
        return list.stream().map(MallProductTemplateConvert.INSTANCE::itemToVo).collect(Collectors.toList());
    }

    /**
     * 为列表行填充「已绑定类目」的层级名称（自顶向下「 / 」；多类目「；」分隔）。
     */
    private void fillLinkedCategoryPaths(List<MallProductTemplateListVO> rows) {
        if (CollUtil.isEmpty(rows)) {
            return;
        }
        List<String> templateIds =
            rows.stream().map(MallProductTemplateListVO::getId).filter(StrUtil::isNotBlank).distinct().toList();
        List<MallCategory> linked = mallCategoryService.listByTemplateIds(templateIds);
        Map<String, List<MallCategory>> byTemplate =
            linked.stream()
                .filter(c -> StrUtil.isNotBlank(c.getTemplateId()))
                .collect(Collectors.groupingBy(MallCategory::getTemplateId));

        Map<String, MallCategory> nodeMap = new HashMap<>();
        ArrayDeque<String> pending = new ArrayDeque<>();
        for (MallCategory c : linked) {
            if (StrUtil.isNotBlank(c.getId())) {
                pending.add(c.getId().trim());
            }
        }
        while (!pending.isEmpty()) {
            List<String> chunk = new ArrayList<>();
            while (!pending.isEmpty() && chunk.size() < 500) {
                String id = pending.pollFirst();
                if (StrUtil.isBlank(id) || nodeMap.containsKey(id.trim())) {
                    continue;
                }
                chunk.add(id.trim());
            }
            if (chunk.isEmpty()) {
                continue;
            }
            List<MallCategory> loaded = mallCategoryService.listByIds(chunk);
            for (MallCategory n : loaded) {
                nodeMap.put(n.getId(), n);
                String pid = n.getParentId();
                if (StrUtil.isNotBlank(pid) && !"0".equals(pid.trim()) && !nodeMap.containsKey(pid.trim())) {
                    pending.addLast(pid.trim());
                }
            }
        }

        for (MallProductTemplateListVO row : rows) {
            List<MallCategory> cats = byTemplate.get(row.getId());
            if (CollUtil.isEmpty(cats)) {
                row.setLinkedCategoryPaths("—");
                continue;
            }
            String text =
                cats.stream()
                    .map(c -> buildCategoryHierarchyName(c.getId(), nodeMap))
                    .filter(StrUtil::isNotBlank)
                    .distinct()
                    .sorted()
                    .collect(Collectors.joining("； "));
            row.setLinkedCategoryPaths(StrUtil.isBlank(text) ? "—" : text);
        }
    }

    /**
     * 自叶子向根拼接类目层级名称，例如「一级 / 二级 / 当前」。
     */
    private String buildCategoryHierarchyName(String leafId, Map<String, MallCategory> byId) {
        if (StrUtil.isBlank(leafId)) {
            return "";
        }
        List<String> segments = new ArrayList<>();
        String cur = leafId.trim();
        int guard = 0;
        while (StrUtil.isNotBlank(cur) && guard++ < 64) {
            MallCategory node = byId.get(cur);
            if (node == null) {
                segments.add(0, "…");
                break;
            }
            segments.add(0, StrUtil.blankToDefault(node.getCategoryName(), "未命名"));
            String pid = node.getParentId();
            if (StrUtil.isBlank(pid) || "0".equals(pid.trim())) {
                break;
            }
            cur = pid.trim();
        }
        return String.join(" / ", segments);
    }
}
