package com.seer.teach.mall.good.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.google.common.collect.Lists;
import com.seer.teach.common.enums.EntityDeleteFlagEnums;
import com.seer.teach.common.enums.GoodSaleEnum;
import com.seer.teach.common.enums.ResultCodeEnum;
import com.seer.teach.common.exception.CommonException;
import com.seer.teach.common.utils.AssertUtils;
import com.seer.teach.common.utils.CommonUtils;
import com.seer.teach.mall.convert.GoodConverter;
import com.seer.teach.mall.entity.GoodsEntity;
import com.seer.teach.mall.entity.GoodsLogEntity;
import com.seer.teach.mall.entity.GoodsSpecificationAttributeEntity;
import com.seer.teach.mall.entity.GoodsSpecificationEntity;
import com.seer.teach.mall.enums.GoodsStatusEnum;
import com.seer.teach.mall.good.service.IAdminGoodsService;
import com.seer.teach.mall.request.GoodsAuditReq;
import com.seer.teach.mall.request.GoodsReq;
import com.seer.teach.mall.request.GoodsSpecificationReq;
import com.seer.teach.mall.response.GoodsResp;
import com.seer.teach.mall.service.IGoodsLogService;
import com.seer.teach.mall.service.IGoodsService;
import com.seer.teach.mall.service.IGoodsSpecificationAttributeService;
import com.seer.teach.mall.service.IGoodsSpecificationService;
import com.seer.teach.mall.util.GoodChangeUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class AdminGoodsServiceImpl implements IAdminGoodsService {

    private final IGoodsService goodsService;

    private final IGoodsSpecificationService goodsSpecificationService;

    private final IGoodsLogService goodsLogService;

    private final IGoodsSpecificationAttributeService goodsSpecificationAttributeService;

    @Override
    public IPage<GoodsEntity> queryPageList(Integer size, Integer current, GoodsEntity goods) {
        return goodsService.queryPageList(size, current, goods);
    }


    @Override
    public GoodsResp queryDetail(Integer id) {
        return goodsService.queryDetail(id);
    }

    @Override
    public boolean back(List<Integer> ids) {
        int updateResult = updateDeleteBatchByIds(EntityDeleteFlagEnums.UN_DELETE_FLAG,ids);
        log.info("back result : {}",updateResult);
        
        // 记录操作日志
        if (updateResult > 0) {
            int userId = StpUtil.getLoginIdAsInt();
            List<GoodsLogEntity> logList = ids.stream().map(id -> {
                GoodsLogEntity log = new GoodsLogEntity();
                log.setGoodsId(id);
                log.setOperatorId(userId);
                // 修改为JSON格式
                JSONObject content = new JSONObject();
                content.put("operation", "商品恢复");
                log.setOperatorContent(content.toJSONString());
                return log;
            }).collect(Collectors.toList());
            goodsLogService.saveBatch(logList);
        }
        
        return updateResult > 0;
    }

    @Override
    public boolean enSale(List<Integer> ids) {
        int userId = StpUtil.getLoginIdAsInt();
        if(CollUtil.isEmpty(ids)){
            log.info("ids is empty");
            return false;
        }
        List<GoodsEntity> goodsEntities = goodsService.listByIds(ids);
        AssertUtils.notEmpty(goodsEntities, ResultCodeEnum.GOOD_NOT_FOUND);
        Optional<GoodsEntity> any = goodsEntities.stream().filter(goodsEntity -> GoodsStatusEnum.APPROVED.getCode().intValue() != goodsEntity.getStatus()).findAny();
        if(any.isPresent()){
            throw new CommonException(ResultCodeEnum.GOOD_NOT_APPROVE,String.format(ResultCodeEnum.GOOD_NOT_APPROVE.getMsg(),  any.get().getName()));
        }
        GoodsEntity goods = new GoodsEntity();
        goods.setIsOnSale(GoodSaleEnum.ON_SALE.getCode());
        goods.setOnSaleTime(LocalDateTime.now());
        goods.setUpdateTime(LocalDateTime.now());
        goods.setUpdateBy(String.valueOf(userId));
        int updateResult = batchUpdateSaleByIds(ids,goods);
        log.info("enSale result : {}",updateResult);
        
        // 记录操作日志
        if (updateResult > 0) {

            List<GoodsLogEntity> logList = ids.stream().map(id -> {
                GoodsLogEntity log = new GoodsLogEntity();
                log.setGoodsId(id);
                log.setOperatorId(userId);
                // 修改为JSON格式
                JSONObject content = new JSONObject();
                content.put("operation", "上架");
                log.setOperatorContent(content.toJSONString());
                log.setCreateTime(LocalDateTime.now());
                return log;
            }).collect(Collectors.toList());
            goodsLogService.saveBatch(logList);
        }
        
        return updateResult > 0;
    }

    @Override
    public boolean unSale(List<Integer> ids) {
        GoodsEntity goods = new GoodsEntity();
        goods.setIsOnSale(GoodSaleEnum.UN_SALE.getCode());
        goods.setOffSaleTime(LocalDateTime.now());
        int updateResult = batchUpdateSaleByIds(ids,goods);
        log.info("unSale result : {}",updateResult);
        
        // 记录操作日志
        if (updateResult > 0) {
            int userId = StpUtil.getLoginIdAsInt();
            List<GoodsLogEntity> logList = ids.stream().map(id -> {
                GoodsLogEntity log = new GoodsLogEntity();
                log.setGoodsId(id);
                log.setOperatorId(userId);
                // 修改为JSON格式
                JSONObject content = new JSONObject();
                content.put("operation", "下架");
                log.setOperatorContent(content.toJSONString());
                return log;
            }).collect(Collectors.toList());
            goodsLogService.saveBatch(logList);
        }
        
        return updateResult > 0;
    }

    @Override
    public int updateDeleteBatchByIds(EntityDeleteFlagEnums deleteFlagEnums, List<Integer> ids) {
        List<List<Integer>> lists = Lists.partition(ids, 100);
        int userId = StpUtil.getLoginIdAsInt();
        int updateResult = 0;
        for(List<Integer> list : lists){
            updateResult += goodsService.updateDeleteBatchByIds(deleteFlagEnums,list,userId);
        }
        
        // 记录操作日志
        if (updateResult > 0) {
            List<GoodsLogEntity> logList = ids.stream().map(id -> {
                GoodsLogEntity log = new GoodsLogEntity();
                log.setGoodsId(id);
                log.setOperatorId(userId);
                // 修改为JSON格式
                JSONObject content = new JSONObject();
                content.put("operation", deleteFlagEnums == EntityDeleteFlagEnums.DELETE_FLAG ? "商品删除" : "商品恢复");
                log.setOperatorContent(content.toJSONString());
                return log;
            }).collect(Collectors.toList());
            goodsLogService.saveBatch(logList);
        }
        
        return updateResult;
    }

    private int batchUpdateSaleByIds(List<Integer> ids,GoodsEntity goods){
        List<List<Integer>> lists = Lists.partition(ids, 100);
        int userId = StpUtil.getLoginIdAsInt();
        int updateResult = 0;
        for(List<Integer> idList : lists){
            updateResult += goodsService.batchUpdateSaleByIds(idList,userId,goods);
        }
        return updateResult;
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveGoods(GoodsReq goodsReq) {
        int userId = StpUtil.getLoginIdAsInt();
        long count = goodsService.count(new LambdaQueryWrapper<>(GoodsEntity.class).eq(GoodsEntity::getName, goodsReq.getName()));
        AssertUtils.isTrue(count == 0, ResultCodeEnum.GOOD_NAME_ALREADY_EXISTS);

        //保存商品信息
        GoodsEntity goodsEntity = GoodConverter.INSTANCE.toEntity(goodsReq);
        goodsEntity.setMerchantUserId(goodsReq.getMerchantId());
        goodsEntity.setAddTime(LocalDateTime.now());
        // 初始化 SPU 中 SKU 相关属性
        initSpuFromSkus(goodsEntity, goodsReq.getSpecifications());

        boolean saved = goodsService.save(goodsEntity);
        log.info("用户[{}]保存商品结果：{}", userId,saved);

        Integer goodsId = goodsEntity.getId();
        log.info("用户[{}]保存商品ID：{}", userId,goodsId);

        //保存商品规格信息
        List<GoodsSpecificationReq> specList = goodsReq.getSpecifications();

        if(specList != null && !specList.isEmpty()){
            List<GoodsSpecificationEntity> specificationEntityList = GoodConverter.INSTANCE.toSpecificationEntityList(specList);
            for (GoodsSpecificationEntity specEntity : specificationEntityList){
                specEntity.setGoodsId(goodsId);
                specEntity.setMerchantUserId(goodsReq.getMerchantId());
            }
            boolean saveBatch = goodsSpecificationService.saveBatch(specificationEntityList);
            log.info("用户[{}]保存商品规格结果：{}", userId, saveBatch);
            if(saveBatch){
                List<GoodsSpecificationAttributeEntity> attributes = getGoodsSpecificationAttributeEntities(specificationEntityList);
                boolean saveBatchAttributes = goodsSpecificationAttributeService.saveBatch(attributes);
                log.info("用户[{}]保存商品规格属性结果：{}", userId, saveBatchAttributes);
            }
        }
        GoodsLogEntity goodsLog = new GoodsLogEntity();
        goodsLog.setGoodsId(goodsId);
        goodsLog.setOperatorId(StpUtil.getLoginIdAsInt());
        JSONObject content = new JSONObject();
        content.put("operation", "新增商品" + goodsEntity.getName());
        goodsLog.setOperatorContent(content.toJSONString());
        goodsLogService.save(goodsLog);
        return true;
    }

    private List<GoodsSpecificationAttributeEntity> getGoodsSpecificationAttributeEntities(List<GoodsSpecificationEntity> specificationEntityList) {
        List<GoodsSpecificationAttributeEntity> attributes = new ArrayList<>();
        for(GoodsSpecificationEntity specEntity : specificationEntityList){
            List<GoodsSpecificationEntity.Attribute> attributeList = specEntity.getAttributes();
            for(GoodsSpecificationEntity.Attribute attribute : attributeList){
                GoodsSpecificationAttributeEntity attributeEntity = new GoodsSpecificationAttributeEntity();
                attributeEntity.setSkuId(specEntity.getId());
                attributeEntity.setSpuId(specEntity.getGoodsId());
                attributeEntity.setAttributeId(attribute.getAttributeId());
                attributeEntity.setAttributeName(attribute.getAttributeName());
                attributeEntity.setValueId(attribute.getValueId());
                attributeEntity.setValueName(attribute.getValueName());
                attributes.add(attributeEntity);
            }
        }
        return attributes;
    }

    private void initSpuFromSkus(GoodsEntity goodsEntity, List<GoodsSpecificationReq> specifications) {
        // sku 单价最低的商品的价格
        goodsEntity.setPrice(CommonUtils.getMinValue(specifications, GoodsSpecificationReq::getPrice));
        // sku 单价最低的商品的市场价格
        goodsEntity.setMarketPrice(CommonUtils.getMinValue(specifications, GoodsSpecificationReq::getMarketPrice));
        // sku 单价最低的商品的成本价格
        goodsEntity.setCostPrice(CommonUtils.getMinValue(specifications, GoodsSpecificationReq::getCostPrice));
        // skus 库存总数
        goodsEntity.setStock(CommonUtils.getSumValue(specifications, GoodsSpecificationReq::getStock, Long::sum));
    }

    @Override
    public boolean auditGoods(GoodsAuditReq goodsAuditReq) {
        String userId = StpUtil.getLoginIdAsString();
        List<Integer> ids = goodsAuditReq.getIds();
        List<GoodsEntity> goodsList = goodsService.listByIds(ids);
        AssertUtils.notEmpty(goodsList, ResultCodeEnum.GOOD_NOT_FOUND);

        // 检查是否有非待审核状态的商品
        Optional<GoodsEntity> nonPendingGoods = goodsList.stream()
                .filter(goods -> !GoodsStatusEnum.PENDING_REVIEW.getCode().equals(goods.getStatus()))
                .findAny();

        if (nonPendingGoods.isPresent()) {
            GoodsEntity goods = nonPendingGoods.get();
            throw new CommonException(
                    ResultCodeEnum.GOOD_NON_PENDING_REVIEW,
                    String.format(ResultCodeEnum.GOOD_NOT_APPROVE.getMsg(), goods.getName())
            );
        }
        Integer status = goodsAuditReq.getStatus();
        // 更新商品状态
        boolean result = goodsService.update(new LambdaUpdateWrapper<>(GoodsEntity.class)
                .set(GoodsEntity::getStatus, status)
                .in(GoodsEntity::getId, ids));
        log.info("用户[{}]审核商品结果：{}", userId, result);
        if (result) {
            // 记录审核日志
            List<GoodsLogEntity> logList = goodsList.stream().map(goods -> {
                GoodsLogEntity log = new GoodsLogEntity();
                log.setGoodsId(goods.getId());
                log.setOperatorId(Integer.valueOf(userId));
                // 修改为JSON格式
                JSONObject content = new JSONObject();
                content.put("operation", GoodsStatusEnum.APPROVED.getCode().intValue() == status ? "审核通过" : "审核拒绝");
                content.put("remark", goodsAuditReq.getRemark());
                log.setOperatorContent(content.toJSONString());
                log.setTenantId(goods.getTenantId());
                return log;
            }).collect(Collectors.toList());
            goodsLogService.saveBatch(logList);
        }
        return result;
    }

    @Override
    public List<GoodsEntity> listByIds(List<Integer> goodsIds) {
        if(CollUtil.isEmpty(goodsIds)){
            return Collections.emptyList();
        }
        return goodsService.listByIds(goodsIds);
    }

    @Override
    public boolean update(Integer id, GoodsReq goodsReq) {
        Integer userId = StpUtil.getLoginIdAsInt();
        GoodsEntity oldGoods = goodsService.getById(id);
        AssertUtils.notNull(oldGoods, ResultCodeEnum.GOOD_NOT_FOUND);
        AssertUtils.isTrue(GoodSaleEnum.UN_SALE.getCode().intValue() == oldGoods.getIsOnSale(), ResultCodeEnum.GOOD_UPDATE_ON_SALE);
        GoodsEntity goodsEntity = GoodConverter.INSTANCE.toEntity(goodsReq);
        goodsEntity.setId(id);
        initSpuFromSkus(goodsEntity, goodsReq.getSpecifications());

        boolean updateResult = update(goodsEntity);
        log.info("updateResult:{}", updateResult);

        // 获取旧的规格信息
        List<GoodsSpecificationEntity> oldSpecs = goodsSpecificationService.list(new LambdaQueryWrapper<>(GoodsSpecificationEntity.class)
                .eq(GoodsSpecificationEntity::getGoodsId, id));

        List<GoodsSpecificationEntity> specificationEntityList = GoodConverter.INSTANCE.toSpecificationEntityList(goodsReq.getSpecifications());
        for(GoodsSpecificationEntity specEntity : specificationEntityList){
            specEntity.setGoodsId(id);
            specEntity.setMerchantUserId(oldGoods.getMerchantUserId());
        }

        if(CollectionUtil.isNotEmpty(specificationEntityList)){
            boolean saveOrUpdateBatchResult = goodsSpecificationService.saveOrUpdateBatch(specificationEntityList);
            log.info("spSaveResult:{}", saveOrUpdateBatchResult);
            List<GoodsSpecificationAttributeEntity> attributes = getGoodsSpecificationAttributeEntities(specificationEntityList);
            boolean saveBatchAttributes = goodsSpecificationAttributeService.saveOrUpdateBatch(attributes);
            log.info("用户[{}]更新商品规格属性结果：{}", userId, saveBatchAttributes);
        }
        // 记录操作日志
        if (updateResult) {
            saveOperationLog(id, oldGoods, goodsEntity, oldSpecs, specificationEntityList);
        }

        return updateResult;
    }

    @Override
    public boolean updateBaseInfo(Integer id, GoodsReq goods) {
        GoodsEntity oldGoods = goodsService.getById(id);
        AssertUtils.notNull(oldGoods, ResultCodeEnum.GOOD_NOT_FOUND);
        AssertUtils.isTrue(GoodSaleEnum.UN_SALE.getCode().intValue() == oldGoods.getIsOnSale(), ResultCodeEnum.GOOD_UPDATE_ON_SALE);
        GoodsEntity newGoods = GoodConverter.INSTANCE.toEntity(goods);
        newGoods.setId(id);

        boolean result = update(newGoods);

        // 记录操作日志
        if (result) {
            saveOperationLog(id, oldGoods, newGoods, null, null);
        }
        return result;
    }

    private boolean update(GoodsEntity goods) {
        boolean updateByIdResult = goodsService.updateById(goods);
        log.info("updateByIdResult:{}", updateByIdResult);
        return updateByIdResult;
    }

    /**
     * 保存操作日志
     */
    private void saveOperationLog(Integer goodsId, GoodsEntity oldGoods, GoodsEntity newGoods,
                                  List<GoodsSpecificationEntity> oldSpecs, List<GoodsSpecificationEntity> newSpecs) {
        GoodsLogEntity goodsLog = new GoodsLogEntity();
        goodsLog.setGoodsId(goodsId);
        goodsLog.setOperatorId(StpUtil.getLoginIdAsInt());

        // 构建JSON格式的操作内容
        JSONObject logContent = new JSONObject();
        logContent.put("goodsChanges", GoodChangeUtils.buildGoodChangeLogJson(oldGoods, newGoods));
        if(CollUtil.isNotEmpty(oldSpecs) && CollUtil.isNotEmpty(newSpecs)){
            logContent.put("specChanges", GoodChangeUtils.buildSpecificationChangeLogJson(oldSpecs, newSpecs));
        }
        goodsLog.setOperatorContent(logContent.toJSONString());
        goodsLogService.save(goodsLog);
    }


}