package com.czg.service.product.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.constant.GlobalConstant;
import com.czg.constants.SystemConstants;
import com.czg.exception.CzgException;
import com.czg.product.dto.ShopProdSpecDTO;
import com.czg.product.entity.ShopProdSpec;
import com.czg.product.service.ShopProdSpecService;
import com.czg.sa.StpKit;
import com.czg.service.product.mapper.ShopProdSpecMapper;
import com.czg.utils.AssertUtil;
import com.czg.utils.PageUtil;
import com.czg.utils.TreeUtils;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import com.mybatisflex.core.row.DbChain;
import com.mybatisflex.core.update.UpdateChain;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

import static com.czg.product.entity.table.ShopProdSpecTableDef.SHOP_PROD_SPEC;


/**
 * 商品规格
 *
 * @author Tankaikai tankaikai@aliyun.com
 * @since 1.0 2025-02-13
 */
@Service
public class ShopProductSpecServiceImpl extends ServiceImpl<ShopProdSpecMapper, ShopProdSpec> implements ShopProdSpecService {

    private QueryWrapper buildQueryWrapper(ShopProdSpecDTO param) {
        QueryWrapper queryWrapper = PageUtil.buildSortQueryWrapper();
        if (ObjUtil.isNotNull(param.getPid())) {
            queryWrapper.and(q -> {
                q.eq(ShopProdSpec::getId, param.getPid()).or(r -> {
                    r.like(ShopProdSpec::getPids, "," + param.getPid() + ",");
                });
            });
        }
        if (StrUtil.isNotEmpty(param.getName())) {
            queryWrapper.like(ShopProdSpec::getFullName, param.getName());
        }
        if (ObjUtil.isNotNull(param.getLevel())) {
            queryWrapper.like(ShopProdSpec::getLevel, param.getLevel());
        }
        Long shopId = StpKit.USER.getShopId(0L);
        queryWrapper.eq(ShopProdSpec::getShopId, shopId);
        queryWrapper.orderBy(ShopProdSpec::getLevel, true);
        queryWrapper.orderBy(ShopProdSpec::getSort, true);
        queryWrapper.orderBy(ShopProdSpec::getId, false);
        return queryWrapper;
    }

    @Override
    public Page<ShopProdSpecDTO> getShopProdSpecPage(ShopProdSpecDTO param) {
        QueryWrapper queryWrapper = buildQueryWrapper(param);
        return super.pageAs(PageUtil.buildPage(), queryWrapper, ShopProdSpecDTO.class);
    }

    @Override
    public List<ShopProdSpecDTO> getShopProdSpecList(ShopProdSpecDTO param) {
        QueryWrapper queryWrapper = buildQueryWrapper(param);
        queryWrapper.eq(ShopProdSpec::getStatus, SystemConstants.OneZero.ONE);
        List<ShopProdSpecDTO> list = super.listAs(queryWrapper, ShopProdSpecDTO.class);
        return TreeUtils.build(list, CollUtil.isEmpty(list) ? GlobalConstant.TREE_ROOT : list.getFirst().getPid());
    }

    @Override
    public ShopProdSpecDTO getShopProdSpecById(Long id) {
        Long shopId = StpKit.USER.getShopId(0L);
        return super.getOneAs(query().eq(ShopProdSpec::getId, id).eq(ShopProdSpec::getShopId, shopId), ShopProdSpecDTO.class);
    }

    @Override
    public void addShopProdSpec(ShopProdSpecDTO dto) {
        Long shopId = StpKit.USER.getShopId(0L);
        boolean exists = super.exists(query()
                .eq(ShopProdSpec::getName, dto.getName())
                .eq(ShopProdSpec::getPid, dto.getPid())
                .eq(ShopProdSpec::getLevel, dto.getLevel())
                .eq(ShopProdSpec::getShopId, shopId));
        if (exists) {
            throw new CzgException(StrUtil.format("模板/规格名称【{}】已存在", dto.getName()));
        }
        ShopProdSpec entity = BeanUtil.copyProperties(dto, ShopProdSpec.class);
        if (GlobalConstant.TREE_ROOT.equals(entity.getPid())) {
            entity.setFullName(entity.getName());
            entity.setPids(GlobalConstant.TREE_ROOT + ",");
        } else {
            ShopProdSpec parent = super.getById(entity.getPid());
            entity.setFullName(parent.getFullName() + " - " + entity.getName());
            String pids = parent.getPids();
            entity.setPids(pids + entity.getPid() + ",");
        }
        entity.setStatus(SystemConstants.OneZero.ONE);
        entity.setShopId(shopId);
        super.save(entity);
        dto.setId(entity.getId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateShopProdSpec(ShopProdSpecDTO dto) {
        List<Long> affectedIdList = new ArrayList<>();
        //上级规格不能为自身
        if (dto.getId().equals(dto.getPid())) {
            throw new CzgException("上级规格不能为自身");
        }
        Long shopId = StpKit.USER.getShopId(0L);
        dto.setShopId(shopId);
        boolean exists = super.exists(query()
                .eq(ShopProdSpec::getName, dto.getName())
                .eq(ShopProdSpec::getPid, dto.getPid())
                .eq(ShopProdSpec::getLevel, dto.getLevel())
                .eq(ShopProdSpec::getShopId, shopId)
                .ne(ShopProdSpec::getId, dto.getId()));
        if (exists) {
            throw new CzgException(StrUtil.format("模板/规格名称【{}】已存在", dto.getName()));
        }
        ShopProdSpec old = super.getById(dto.getId());
        ShopProdSpec entity = BeanUtil.copyProperties(dto, ShopProdSpec.class);
        if (GlobalConstant.TREE_ROOT.equals(entity.getPid())) {
            entity.setFullName(entity.getName());
            entity.setPids(GlobalConstant.TREE_ROOT + ",");
        } else {
            ShopProdSpec parent = super.getById(entity.getPid());
            entity.setFullName(parent.getFullName() + " - " + entity.getName());
            String pids = parent.getPids();
            entity.setPids(pids + entity.getPid() + ",");
        }
        String oldName = old.getName();
        UpdateChain.of(ShopProdSpec.class)
                .setRaw(ShopProdSpec::getFullName, StrUtil.format("replace(full_name, '{}', '{}')", oldName, entity.getName()))
                .like(ShopProdSpec::getPids, "," + entity.getId() + ",")
                .eq(ShopProdSpec::getShopId, entity.getShopId()).update();
        super.updateById(entity);
        affectedIdList.add(entity.getId());
        List<Long> ids = DbChain.table("tb_shop_prod_spec").select("id").where("pids like concat('%,',?,',%') and shop_id = ?", entity.getId(), entity.getShopId()).listAs(Long.class);
        affectedIdList.addAll(ids);
        dto.setAffectedIdList(affectedIdList);
    }

    @Override
    public void deleteShopProdSpec(Long id) {
        Long shopId = StpKit.USER.getShopId(0L);
        super.remove(query()
                .where(SHOP_PROD_SPEC.SHOP_ID.eq(shopId)
                        .and(SHOP_PROD_SPEC.ID.eq(id).or(SHOP_PROD_SPEC.PIDS.like("," + id + ","))))
        );
    }

    @Override
    public void disableShopProdSpec(Long id) {
        Long shopId = StpKit.USER.getShopId(0L);
        UpdateChain.of(ShopProdSpec.class)
                .set(SHOP_PROD_SPEC.STATUS, SystemConstants.OneZero.ZERO)
                .where(SHOP_PROD_SPEC.SHOP_ID.eq(shopId)
                        .and(SHOP_PROD_SPEC.ID.eq(id).or(SHOP_PROD_SPEC.PIDS.like("," + id + ",")))).update();
    }

    @Override
    public void enableShopProdSpec(Long id) {
        Long shopId = StpKit.USER.getShopId(0L);
        UpdateChain.of(ShopProdSpec.class)
                .set(SHOP_PROD_SPEC.STATUS,SystemConstants.OneZero.ONE)
                .where(SHOP_PROD_SPEC.SHOP_ID.eq(shopId)
                        .and(SHOP_PROD_SPEC.ID.eq(id).or(SHOP_PROD_SPEC.PIDS.like("," + id + ",")))).update();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void quickAddShopProdSpec(ShopProdSpecDTO dto) {
        List<Long> affectedIdList = new ArrayList<>();
        String name = dto.getName();
        AssertUtil.isBlank(name, "1级规格名称不能为空");
        List<ShopProdSpecDTO> level2List = dto.getChildren();
        AssertUtil.isListEmpty(level2List, "2级规格数据不能为空");
        for (ShopProdSpecDTO level2Dto : level2List) {
            AssertUtil.isBlank(level2Dto.getName(), "2级规格名称不能为空");
        }
        long count = level2List.stream().map(ShopProdSpecDTO::getName).distinct().count();
        if (count != level2List.size()) {
            throw new CzgException("2级规格名称不能重复");
        }
        for (ShopProdSpecDTO level2Dto : level2List) {
            List<ShopProdSpecDTO> level3List = level2Dto.getChildren();
            AssertUtil.isListEmpty(level3List, "3级规格数据不能为空");
            level3List.forEach(level3Dto -> {
                AssertUtil.isBlank(level3Dto.getName(), "3级规格名称不能为空");
            });
            count = level3List.stream().map(ShopProdSpecDTO::getName).distinct().count();
            if (count != level3List.size()) {
                throw new CzgException("3级规格名称不能重复");
            }
        }
        dto.setLevel(1);
        Long maxId = super.mapper.selectOneByQueryAs(query().select("max(id)").eq(ShopProdSpec::getShopId, StpKit.USER.getShopId()), Long.class);
        dto.setSort(ObjUtil.defaultIfNull(maxId, 0).intValue() + 1);
        dto.setPid(GlobalConstant.TREE_ROOT);
        addShopProdSpec(dto);
        affectedIdList.add(dto.getId());
        int xIndex = 0;
        for (ShopProdSpecDTO level2Dto : level2List) {
            xIndex++;
            level2Dto.setLevel(2);
            level2Dto.setSort(xIndex);
            level2Dto.setPid(dto.getId());
            addShopProdSpec(level2Dto);
            affectedIdList.add(level2Dto.getId());
            List<ShopProdSpecDTO> level3List = level2Dto.getChildren();
            int yIndex = 0;
            for (ShopProdSpecDTO level3Dto : level3List) {
                yIndex++;
                level3Dto.setLevel(3);
                level3Dto.setSort(yIndex);
                level3Dto.setPid(level2Dto.getId());
                addShopProdSpec(level3Dto);
                affectedIdList.add(level3Dto.getId());
            }
        }
        dto.setAffectedIdList(affectedIdList);
    }

    @Override
    public ShopProdSpecDTO getShopProdSpecTreeById(Long id) {
        ShopProdSpecDTO param = new ShopProdSpecDTO();
        param.setPid(id);
        List<ShopProdSpecDTO> list = getShopProdSpecList(param);
        AssertUtil.isListEmpty(list, "规格信息不存在");
        return list.getFirst();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void quickUpdateShopProdSpec(ShopProdSpecDTO dto) {
        deleteShopProdSpec(dto.getId());
        quickAddShopProdSpec(dto);
    }
}