package com.liquidnet.client.admin.zhengzai.goblin.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.liquidnet.client.admin.zhengzai.goblin.dto.SqbPerfGoodsBindItemParam;
import com.liquidnet.client.admin.zhengzai.goblin.service.ISqbPerformanceGoodsService;
import com.liquidnet.client.admin.zhengzai.goblin.utils.GoblinRedisUtils;
import com.liquidnet.service.base.ResponseDto;
import com.liquidnet.service.goblin.dto.vo.GoblinAdminSqbGoodsVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinGoodsSkuInfoVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfLinkedGoodsVo;
import com.liquidnet.service.goblin.dto.vo.GoblinSqbPerfListRespVo;
import com.liquidnet.service.goblin.entity.GoblinGoods;
import com.liquidnet.service.goblin.entity.GoblinGoodsSku;
import com.liquidnet.service.goblin.entity.GoblinSqbPerformanceConfig;
import com.liquidnet.service.goblin.entity.GoblinSqbPerformanceGoods;
import com.liquidnet.service.goblin.mapper.GoblinGoodsMapper;
import com.liquidnet.service.goblin.mapper.GoblinGoodsSkuMapper;
import com.liquidnet.service.goblin.mapper.GoblinSqbPerformanceConfigMapper;
import com.liquidnet.service.goblin.mapper.GoblinSqbPerformanceGoodsMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 演出-收钱吧商品关联 服务实现
 * 直连 MySQL，写入/删除时同步删除 Redis 缓存
 */
@Slf4j
@Service
public class SqbPerformanceGoodsServiceImpl implements ISqbPerformanceGoodsService {

    /** skuType=33 代表收钱吧商品 */
    private static final int SQB_SKU_TYPE = 33;

    /**
     * 与实体/上下架接口约定一致：0-待上架|1-下架|2-违规|3-上架（见 {@link GoblinGoods#getShelvesStatus} 注释）
     */
    private static final String SHELF_WAIT = "0";
    private static final String SHELF_OFF = "1";
    private static final String SHELF_VIOLATION = "2";
    private static final String SHELF_ON = "3";

    private static String trimFlg(String s) {
        return s == null ? "" : s.trim();
    }

    /** 演出关联列表：是否可售 + 展示文案（与 C 端 {@code GoblinFrontServiceImpl#getPerformanceSelectGoods} 过滤条件对齐） */
    private static final class PerfShelfEval {
        final boolean linkable;
        final String statusLabel;

        PerfShelfEval(boolean linkable, String statusLabel) {
            this.linkable = linkable;
            this.statusLabel = statusLabel;
        }
    }

    /**
     * 上下架/可售判断：与店铺 {@code POST store/mgt/goods/list} 一致——该列表的 {@code shelvesStatus} 来自 Mongo
     * {@link com.liquidnet.service.goblin.dto.vo.GoblinGoodsInfoVo}（见 {@code GoblinMongoUtils#getMgtGoodsInfoVos}），
     * 不是读 MySQL；admin 模块无 Mongo 时以 Redis（与 goblin 缓存同源）为准，MySQL 仅兜底。
     */
    private PerfShelfEval evalShelfState(String skuId, String spuId, GoblinGoodsSku mysqlSku, GoblinGoods mysqlSpu) {
        String sid = skuId == null ? "" : skuId.trim();
        String pid = spuId == null ? "" : spuId.trim();
        if (!StringUtils.hasText(sid) || !StringUtils.hasText(pid)) {
            return new PerfShelfEval(false, "数据异常");
        }
        GoblinGoodsSkuInfoVo skuVo = goblinRedisUtils.getGoodsSkuInfoVo(sid);
        GoblinGoodsInfoVo spuVo = goblinRedisUtils.getGoodsInfoVo(pid);
        if (skuVo != null && spuVo != null) {
            return evalFromSnapshot(trimFlg(skuVo.getDelFlg()), trimFlg(spuVo.getDelFlg()),
                    trimFlg(skuVo.getShelvesStatus()), trimFlg(spuVo.getShelvesStatus()),
                    trimFlg(spuVo.getSpuAppear()), spuVo.getMarketId(), true);
        }
        if (mysqlSku == null || mysqlSpu == null) {
            return new PerfShelfEval(false, "缺少商品数据");
        }
        return evalFromSnapshot(trimFlg(mysqlSku.getDelFlg()), trimFlg(mysqlSpu.getDelFlg()),
                trimFlg(mysqlSku.getShelvesStatus()), trimFlg(mysqlSpu.getShelvesStatus()),
                trimFlg(mysqlSpu.getSpuAppear()), null, false);
    }

    /**
     * @param hasMarketId  true 表示来自 Redis，可检查 marketId；MySQL DO 无该字段时传 false
     */
    private static PerfShelfEval evalFromSnapshot(String skuDel, String spuDel, String skuShelf, String spuShelf,
            String spuAppear, String marketId, boolean hasMarketId) {
        if (!"0".equals(skuDel) || !"0".equals(spuDel)) {
            return new PerfShelfEval(false, "已删除");
        }
        if (!"0".equals(spuAppear)) {
            return new PerfShelfEval(false, "SPU隐藏");
        }
        if (hasMarketId && StringUtils.hasText(marketId)) {
            return new PerfShelfEval(false, "活动商品");
        }
        boolean on = SHELF_ON.equals(skuShelf) && SHELF_ON.equals(spuShelf);
        if (on) {
            return new PerfShelfEval(true, "上架");
        }
        return new PerfShelfEval(false, humanizeNotOnShelf(skuShelf, spuShelf));
    }

    /** 非「上架」时的文案：区分待上架(0)、下架(1)、违规(2)，避免把同步初始态 0 误标成「已下架」 */
    private static String humanizeNotOnShelf(String skuShelf, String spuShelf) {
        if (SHELF_WAIT.equals(skuShelf) || SHELF_WAIT.equals(spuShelf)) {
            return "待上架";
        }
        if (SHELF_OFF.equals(skuShelf) || SHELF_OFF.equals(spuShelf)) {
            return "已下架";
        }
        if (SHELF_VIOLATION.equals(skuShelf) || SHELF_VIOLATION.equals(spuShelf)) {
            return "违规";
        }
        return "未上架";
    }

    private static String sqbSpuSkuDisplay(String spuTitle, String skuTitle) {
        String s = spuTitle != null ? spuTitle.trim() : "";
        String k = skuTitle != null ? skuTitle.trim() : "";
        if (!s.isEmpty() && !k.isEmpty()) {
            return s + "-" + k;
        }
        if (!s.isEmpty()) {
            return s;
        }
        return k;
    }

    /** 头图：SKU 无图时回落到 SPU 封面（收钱吧 SKU 常未维护 sku_pic） */
    private static String pickSkuOrSpuCover(String skuPic, String spuCoverPic) {
        if (StringUtils.hasText(skuPic)) {
            return skuPic;
        }
        return StringUtils.hasText(spuCoverPic) ? spuCoverPic : "";
    }

    @Autowired
    private GoblinSqbPerformanceGoodsMapper performanceGoodsMapper;

    @Autowired
    private GoblinSqbPerformanceConfigMapper performanceConfigMapper;

    @Autowired
    private GoblinGoodsMapper goblinGoodsMapper;

    @Autowired
    private GoblinGoodsSkuMapper goblinGoodsSkuMapper;

    @Autowired
    private GoblinRedisUtils goblinRedisUtils;

    @Override
    public ResponseDto<Boolean> bind(String performancesId, List<SqbPerfGoodsBindItemParam> items, Integer autoOffline) {
        if (!StringUtils.hasText(performancesId)) {
            return ResponseDto.failure("演出ID不能为空");
        }
        if (items == null || items.isEmpty()) {
            return ResponseDto.failure("商品列表不能为空");
        }

        LocalDateTime nowTime = LocalDateTime.now();
        String nowStr = nowTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

        try {
            // 1. 保存全局配置
            GoblinSqbPerformanceConfig config = performanceConfigMapper.selectById(performancesId);
            if (config == null) {
                config = new GoblinSqbPerformanceConfig();
                config.setPerformancesId(performancesId);
                config.setAutoOffline(autoOffline != null ? autoOffline : 0);
                config.setCreatedAt(nowStr);
                config.setUpdatedAt(nowStr);
                performanceConfigMapper.insert(config);
            } else {
                config.setAutoOffline(autoOffline != null ? autoOffline : 0);
                config.setUpdatedAt(nowStr);
                performanceConfigMapper.updateById(config);
            }

            // 2. 批量处理商品绑定
            for (SqbPerfGoodsBindItemParam item : items) {
                String skuId = item.getSkuId();
                if (!StringUtils.hasText(skuId)) {
                    continue;
                }

                LambdaQueryWrapper<GoblinGoodsSku> skuQuery = new LambdaQueryWrapper<>();
                skuQuery.eq(GoblinGoodsSku::getSkuId, skuId).last("LIMIT 1");
                GoblinGoodsSku sku = goblinGoodsSkuMapper.selectOne(skuQuery);
                if (sku == null) {
                    log.warn("[演出商品关联] SKU不存在，skuId={}", skuId);
                    return ResponseDto.failure("SKU不存在：" + skuId);
                }

                LambdaQueryWrapper<GoblinSqbPerformanceGoods> existQuery = new LambdaQueryWrapper<>();
                existQuery.eq(GoblinSqbPerformanceGoods::getPerformancesId, performancesId)
                        .eq(GoblinSqbPerformanceGoods::getSkuId, skuId)
                        .last("LIMIT 1");
                GoblinSqbPerformanceGoods existing = performanceGoodsMapper.selectOne(existQuery);

                if (sku.getSkuType() == null || sku.getSkuType() != SQB_SKU_TYPE) {
                    return ResponseDto.failure("仅可关联收钱吧商品（skuType=33），skuId=" + skuId);
                }
                if (existing == null) {
                    GoblinGoods spu = goblinGoodsMapper.selectOne(new LambdaQueryWrapper<GoblinGoods>()
                            .eq(GoblinGoods::getSpuId, sku.getSpuId()).last("LIMIT 1"));
                    if (!evalShelfState(skuId, sku.getSpuId(), sku, spu).linkable) {
                        return ResponseDto.failure("商品未上架或已下架，不可关联。请先让商户上架后再操作。skuId=" + skuId);
                    }
                }

                int sortVal = item.getSort() != null ? item.getSort() : 0;

                if (existing != null) {
                    LambdaUpdateWrapper<GoblinSqbPerformanceGoods> updateWrapper = new LambdaUpdateWrapper<>();
                    updateWrapper.eq(GoblinSqbPerformanceGoods::getPerformancesId, performancesId)
                            .eq(GoblinSqbPerformanceGoods::getSkuId, skuId)
                            .set(GoblinSqbPerformanceGoods::getSort, sortVal)
                            .set(GoblinSqbPerformanceGoods::getStatus, 1)
                            .set(GoblinSqbPerformanceGoods::getSettlementPrice, item.getSettlementPrice())
                            .set(GoblinSqbPerformanceGoods::getUpdatedAt, nowStr);
                    performanceGoodsMapper.update(null, updateWrapper);
                } else {
                    GoblinSqbPerformanceGoods entity = new GoblinSqbPerformanceGoods();
                    entity.setPerformancesId(performancesId);
                    entity.setSpuId(sku.getSpuId());
                    entity.setSkuId(skuId);
                    entity.setSort(sortVal);
                    entity.setStatus(1);
                    entity.setSettlementPrice(item.getSettlementPrice());
                    entity.setCreatedAt(nowStr);
                    entity.setUpdatedAt(nowStr);
                    performanceGoodsMapper.insert(entity);
                }
            }

            goblinRedisUtils.delPerformanceGoodsCache(performancesId);
            return ResponseDto.success(Boolean.TRUE);
        } catch (Exception e) {
            log.error("[演出商品关联] bind 异常，performancesId={}", performancesId, e);
            return ResponseDto.failure("关联操作失败：" + e.getMessage());
        }
    }

    @Override
    public ResponseDto<Boolean> unbind(String performancesId, String skuId) {
        if (!StringUtils.hasText(performancesId)) {
            return ResponseDto.failure("演出ID不能为空");
        }
        if (!StringUtils.hasText(skuId)) {
            return ResponseDto.failure("SKU ID不能为空");
        }

        try {
            LambdaUpdateWrapper<GoblinSqbPerformanceGoods> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(GoblinSqbPerformanceGoods::getPerformancesId, performancesId)
                    .eq(GoblinSqbPerformanceGoods::getSkuId, skuId)
                    .set(GoblinSqbPerformanceGoods::getStatus, 0)
                    .set(GoblinSqbPerformanceGoods::getUpdatedAt,
                            LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            int rows = performanceGoodsMapper.update(null, updateWrapper);

            if (rows == 0) {
                return ResponseDto.failure("关联记录不存在");
            }

            goblinRedisUtils.delPerformanceGoodsCache(performancesId);
            return ResponseDto.success(Boolean.TRUE);
        } catch (Exception e) {
            log.error("[演出商品关联] unbind 异常，performancesId={}, skuId={}", performancesId, skuId, e);
            return ResponseDto.failure("解除关联失败：" + e.getMessage());
        }
    }

    @Override
    public ResponseDto<GoblinSqbPerfListRespVo> list(String performancesId) {
        if (!StringUtils.hasText(performancesId)) {
            return ResponseDto.failure("演出ID不能为空");
        }

        try {
            GoblinSqbPerfListRespVo resp = new GoblinSqbPerfListRespVo();
            
            // 1. 查询全局配置
            GoblinSqbPerformanceConfig config = performanceConfigMapper.selectById(performancesId);
            resp.setAutoOffline(config != null ? config.getAutoOffline() : 0);

            // 2. 查询关联商品
            LambdaQueryWrapper<GoblinSqbPerformanceGoods> query = new LambdaQueryWrapper<>();
            query.eq(GoblinSqbPerformanceGoods::getPerformancesId, performancesId)
                    .eq(GoblinSqbPerformanceGoods::getStatus, 1)
                    .orderByAsc(GoblinSqbPerformanceGoods::getSort);
            List<GoblinSqbPerformanceGoods> relations = performanceGoodsMapper.selectList(query);

            if (relations == null || relations.isEmpty()) {
                resp.setGoodsList(new ArrayList<>());
                return ResponseDto.success(resp);
            }

            List<String> skuIds = relations.stream()
                    .map(GoblinSqbPerformanceGoods::getSkuId).collect(Collectors.toList());

            LambdaQueryWrapper<GoblinGoodsSku> skuQuery = new LambdaQueryWrapper<>();
            skuQuery.in(GoblinGoodsSku::getSkuId, skuIds);
            Map<String, GoblinGoodsSku> skuMap = goblinGoodsSkuMapper.selectList(skuQuery)
                    .stream().collect(Collectors.toMap(GoblinGoodsSku::getSkuId, Function.identity(), (a, b) -> a));

            List<String> spuIdList = relations.stream()
                    .map(GoblinSqbPerformanceGoods::getSpuId)
                    .filter(StringUtils::hasText)
                    .distinct()
                    .collect(Collectors.toList());
            Map<String, String> spuNameById = new HashMap<>();
            Map<String, String> spuCoverById = new HashMap<>();
            Map<String, GoblinGoods> spuById = new HashMap<>();
            if (!spuIdList.isEmpty()) {
                LambdaQueryWrapper<GoblinGoods> goodsQuery = new LambdaQueryWrapper<>();
                goodsQuery.in(GoblinGoods::getSpuId, spuIdList)
                        .select(GoblinGoods::getSpuId, GoblinGoods::getName, GoblinGoods::getCoverPic,
                                GoblinGoods::getShelvesStatus, GoblinGoods::getDelFlg, GoblinGoods::getSpuAppear);
                for (GoblinGoods g : goblinGoodsMapper.selectList(goodsQuery)) {
                    if (g.getSpuId() != null) {
                        spuNameById.put(g.getSpuId(), g.getName());
                        spuCoverById.put(g.getSpuId(), g.getCoverPic());
                        spuById.put(g.getSpuId(), g);
                    }
                }
            }

            List<GoblinSqbPerfLinkedGoodsVo> goodsList = new ArrayList<>();
            for (GoblinSqbPerformanceGoods rel : relations) {
                GoblinSqbPerfLinkedGoodsVo vo = new GoblinSqbPerfLinkedGoodsVo();
                vo.setSkuId(rel.getSkuId());
                vo.setSpuId(rel.getSpuId());
                vo.setSort(rel.getSort());
                vo.setSettlementPrice(rel.getSettlementPrice());
                vo.setStatus(rel.getStatus());

                String relSkuId = rel.getSkuId() == null ? null : rel.getSkuId().trim();
                GoblinGoodsSku sku = relSkuId == null ? null : skuMap.get(relSkuId);
                if (sku != null) {
                    vo.setSkuName(sku.getName());
                    vo.setSpuName(spuNameById.getOrDefault(rel.getSpuId(), ""));
                    vo.setCoverPic(pickSkuOrSpuCover(sku.getSkuPic(), spuCoverById.get(rel.getSpuId())));
                    vo.setPrice(sku.getPrice());
                    vo.setStock(sku.getSkuStock());
                    GoblinGoods spu = spuById.get(rel.getSpuId());
                    PerfShelfEval ev = evalShelfState(relSkuId, rel.getSpuId(), sku, spu);
                    vo.setLinkable(ev.linkable);
                    vo.setShelfStatusLabel(ev.statusLabel);
                } else {
                    vo.setLinkable(false);
                    vo.setShelfStatusLabel("无SKU记录");
                }
                goodsList.add(vo);
            }
            resp.setGoodsList(goodsList);

            return ResponseDto.success(resp);
        } catch (Exception e) {
            log.error("[演出商品关联] list 异常，performancesId={}", performancesId, e);
            return ResponseDto.failure("查询失败：" + e.getMessage());
        }
    }

    @Override
    public ResponseDto<List<GoblinAdminSqbGoodsVo>> searchGoods(String keyword) {
        try {
            LambdaQueryWrapper<GoblinGoodsSku> skuQuery = new LambdaQueryWrapper<>();
            skuQuery.eq(GoblinGoodsSku::getSkuType, SQB_SKU_TYPE).ne(GoblinGoodsSku::getDelFlg, "1");
            if (StringUtils.hasText(keyword)) {
                LambdaQueryWrapper<GoblinGoods> goodsQuery = new LambdaQueryWrapper<>();
                goodsQuery.select(GoblinGoods::getSpuId)
                        .ne(GoblinGoods::getDelFlg, "1")
                        .like(GoblinGoods::getName, keyword)
                        .last("LIMIT 300");
                List<String> spuIds = goblinGoodsMapper.selectList(goodsQuery).stream()
                        .map(GoblinGoods::getSpuId)
                        .filter(StringUtils::hasText)
                        .distinct()
                        .collect(Collectors.toList());
                if (spuIds.isEmpty()) {
                    return ResponseDto.success(new ArrayList<>());
                }
                skuQuery.in(GoblinGoodsSku::getSpuId, spuIds);
            }
            skuQuery.last("LIMIT 50");
            List<GoblinGoodsSku> skuList = goblinGoodsSkuMapper.selectList(skuQuery);

            if (skuList.isEmpty()) {
                return ResponseDto.success(new ArrayList<>());
            }

            List<String> spuIdForTitle = skuList.stream()
                    .map(GoblinGoodsSku::getSpuId)
                    .filter(StringUtils::hasText)
                    .distinct()
                    .collect(Collectors.toList());
            Map<String, String> spuTitleById = new HashMap<>();
            Map<String, String> spuCoverById = new HashMap<>();
            Map<String, GoblinGoods> spuRowById = new HashMap<>();
            if (!spuIdForTitle.isEmpty()) {
                LambdaQueryWrapper<GoblinGoods> gq = new LambdaQueryWrapper<>();
                gq.in(GoblinGoods::getSpuId, spuIdForTitle)
                        .select(GoblinGoods::getSpuId, GoblinGoods::getName, GoblinGoods::getCoverPic,
                                GoblinGoods::getShelvesStatus, GoblinGoods::getDelFlg, GoblinGoods::getSpuAppear);
                for (GoblinGoods g : goblinGoodsMapper.selectList(gq)) {
                    if (g.getSpuId() != null) {
                        spuTitleById.put(g.getSpuId(), g.getName());
                        spuCoverById.put(g.getSpuId(), g.getCoverPic());
                        spuRowById.put(g.getSpuId(), g);
                    }
                }
            }

            List<GoblinAdminSqbGoodsVo> result = new ArrayList<>();
            for (GoblinGoodsSku sku : skuList) {
                GoblinAdminSqbGoodsVo vo = new GoblinAdminSqbGoodsVo();
                vo.setSpuId(sku.getSpuId());
                vo.setSkuId(sku.getSkuId());
                String spuTitle = spuTitleById.getOrDefault(sku.getSpuId(), "");
                String skuTitle = sku.getName() != null ? sku.getName() : "";
                vo.setSpuTitle(spuTitle);
                vo.setSkuTitle(skuTitle);
                GoblinGoods spu = spuRowById.get(sku.getSpuId());
                PerfShelfEval ev = evalShelfState(sku.getSkuId(), sku.getSpuId(), sku, spu);
                vo.setLinkable(ev.linkable);
                vo.setShelfStatusLabel(ev.statusLabel);
                vo.setTitle(sqbSpuSkuDisplay(spuTitle, skuTitle) + (ev.linkable ? "" : "（" + ev.statusLabel + "）"));
                vo.setSkuPic(pickSkuOrSpuCover(sku.getSkuPic(), spuCoverById.get(sku.getSpuId())));
                vo.setPrice(sku.getPrice());
                vo.setSkuStock(sku.getSkuStock());
                result.add(vo);
            }
            return ResponseDto.success(result);
        } catch (Exception e) {
            log.error("[演出商品关联] searchGoods 异常，keyword={}", keyword, e);
            return ResponseDto.failure("搜索失败：" + e.getMessage());
        }
    }

}
