package shop.alien.store.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import shop.alien.entity.store.*;
import shop.alien.entity.store.vo.LifeBlacklistVo;
import shop.alien.mapper.*;
import shop.alien.store.config.BaseRedisService;
import shop.alien.store.service.LifeBlacklistService;
import shop.alien.store.service.clockin.ClockInRecommendCacheService;
import shop.alien.store.service.dynamics.DynamicsRecommendCacheService;
import shop.alien.util.common.JwtUtil;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 黑名单
 * 服务实现类
 * </p>
 *
 * @author ssk
 * @since 2025-04-30
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class LifeBlacklistServiceImpl extends ServiceImpl<LifeBlacklistMapper, LifeBlacklist> implements LifeBlacklistService {

    private final LifeBlacklistMapper lifeBlacklistMapper;
    private final StoreUserMapper storeUserMapper;
    private final LifeUserMapper lifeUserMapper;
    private final StoreImgMapper storeImgMapper;
    private final BaseRedisService baseRedisService;
    private final StoreInfoMapper storeInfoMapper;

    private final DynamicsRecommendCacheService dynamicsRecommendCacheService;

    private final ClockInRecommendCacheService clockInRecommendCacheService;

    @Override
    public int blackList(LifeBlacklist lifeBlacklist) {
        LambdaUpdateWrapper<LifeBlacklist> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(LifeBlacklist::getBlockerId, lifeBlacklist.getBlockerId());
        wrapper.eq(LifeBlacklist::getBlockedId, lifeBlacklist.getBlockedId());
        wrapper.eq(LifeBlacklist::getBlockedType, lifeBlacklist.getBlockedType());
        wrapper.eq(LifeBlacklist::getBlockerType, lifeBlacklist.getBlockerType());
        LifeBlacklist lifeBlacklist1 = lifeBlacklistMapper.selectOne(wrapper);
        if (lifeBlacklist1 != null) {
            return 2;
        }

        // 获取拉黑方phoneId
        String blockerPhoneId = "";
        if ("1".equals(lifeBlacklist.getBlockerType())) {
            StoreUser storeUser = storeUserMapper.selectById(lifeBlacklist.getBlockerId());
            if (storeUser != null) blockerPhoneId = "store_" + storeUser.getPhone();
        } else {
            LifeUser lifeUser = lifeUserMapper.selectById(lifeBlacklist.getBlockerId());
            if (lifeUser != null) blockerPhoneId = "user_" + lifeUser.getUserPhone();
        }

        // 获取被拉黑方phoneId
        String blockedPhoneId = "";
        if ("1".equals(lifeBlacklist.getBlockedType())) {
            StoreUser storeUser = storeUserMapper.selectById(lifeBlacklist.getBlockedId());
            if (storeUser != null) blockedPhoneId = "store_" + storeUser.getPhone();
        } else {
            LifeUser lifeUser = lifeUserMapper.selectById(lifeBlacklist.getBlockedId());
            if (lifeUser != null) blockedPhoneId = "user_" + lifeUser.getUserPhone();
        }
        lifeBlacklist.setBlockerPhoneId(blockerPhoneId);
        lifeBlacklist.setBlockedPhoneId(blockedPhoneId);
        int num = lifeBlacklistMapper.insert(lifeBlacklist);
        if (baseRedisService.hasKey("blackList_" + blockedPhoneId)) {
            baseRedisService.setListRight("blackList_" + blockedPhoneId, blockerPhoneId);
        } else {
            baseRedisService.setSaveOrOverwriteScriptList("blackList_" + blockedPhoneId, Arrays.asList(blockerPhoneId));
        }
        // DB 入库与原有 blackList_* Redis 列表维护已完成；以下为推荐 feeds 增量同步（动态+打卡），失败不改变返回值
        if (num > 0) {
            // dynamics:recommend:v15:* 与 clock_in:recommend:v15:*：仅「用户拉黑商户」写推荐缓存；拉黑用户不写
            try {
                tryPatchDynamicsRecommendBlockedStoresAfterBlack(lifeBlacklist);
            } catch (Exception e) {
                log.error("推荐 feeds 缓存同步失败(拉黑，动态+打卡)，不影响主流程 blockerId={} blockedId={}",
                        lifeBlacklist.getBlockerId(), lifeBlacklist.getBlockedId(), e);
            }
        }
        return num;
    }

    @Override
    public List<LifeBlacklistVo> blackListByUserId(String userType, String userId, Integer type) {
        List<LifeBlacklistVo> lifeBlacklistVos = new ArrayList<>();
        LambdaUpdateWrapper<LifeBlacklist> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(LifeBlacklist::getBlockerId, userId);
        wrapper.eq(LifeBlacklist::getBlockerType, userType);
        if (1 == type) {
            wrapper.eq(LifeBlacklist::getBlockedType, "1");
        } else if (2 == type) {
            wrapper.eq(LifeBlacklist::getBlockedType, "2");
        }else{
            //type == 0 查询拉黑商户和用户
            wrapper.in(LifeBlacklist::getBlockedType,"1","2");
        }
        wrapper.orderByDesc(LifeBlacklist::getCreatedTime);
        List<LifeBlacklist> lifeBlacklists = lifeBlacklistMapper.selectList(wrapper);

        for (LifeBlacklist lifeBlacklist : lifeBlacklists) {
            LifeBlacklistVo vo = new LifeBlacklistVo();
            BeanUtils.copyProperties(lifeBlacklist, vo);
            lifeBlacklistVos.add(vo);
        }

        lifeBlacklistVos.forEach(lifeBlacklist -> {
            if (lifeBlacklist.getBlockedId() != null && lifeBlacklist.getBlockedType() != null) {
                if ("1".equals(lifeBlacklist.getBlockedType())) {
                    StoreUser storeUser = storeUserMapper.selectById(lifeBlacklist.getBlockedId());
                    if(storeUser != null) {
                        StoreInfo storeInfo = storeInfoMapper.selectById(storeUser.getStoreId());
                        lifeBlacklist.setStoreInfo(storeInfo);
                        StoreImg storeImg = null;
                        lifeBlacklist.setName(storeUser.getName());
                        lifeBlacklist.setPhoneId(storeUser.getPhone());
                        lifeBlacklist.setUserImage(storeUser.getHeadImg());
                        storeImg = storeImgMapper.selectOne(new LambdaUpdateWrapper<StoreImg>().eq(StoreImg::getStoreId, storeUser.getStoreId()).eq(StoreImg::getImgType, 10));
                        if (storeImg != null) {
                            lifeBlacklist.setUserImage(storeImg.getImgUrl());
                        }
                    }
                } else {
                    LifeUser lifeUser = lifeUserMapper.selectById(lifeBlacklist.getBlockedId());
                    if (lifeUser != null) {
                        lifeBlacklist.setName(lifeUser.getUserName());
                        lifeBlacklist.setUserImage(lifeUser.getUserImage());
                        lifeBlacklist.setPhoneId(lifeUser.getUserPhone());
                    }

                }
            }
        });
        return lifeBlacklistVos;
    }

    @Override
    public Boolean isBlackListUser(LifeBlacklist lifeBlacklist) {
        LambdaUpdateWrapper<LifeBlacklist> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(LifeBlacklist::getBlockerId, lifeBlacklist.getBlockerId());
        wrapper.eq(LifeBlacklist::getBlockedId, lifeBlacklist.getBlockedId());
        wrapper.eq(LifeBlacklist::getBlockedType, lifeBlacklist.getBlockedType());
        wrapper.eq(LifeBlacklist::getBlockerType, lifeBlacklist.getBlockerType());
        lifeBlacklist = lifeBlacklistMapper.selectOne(wrapper);
        return lifeBlacklist != null;
    }

    @Override
    public int cancelBlacklist(LifeBlacklist lifeBlacklist) {
        LifeBlacklist black = lifeBlacklistMapper.selectById(lifeBlacklist.getId());
        if (black == null) {
            return 0;
        }
        // 保持与原逻辑一致：先维护 blackList_{blockedPhoneId}，再删库
        if (baseRedisService.hasKey("blackList_" + black.getBlockedPhoneId())) {
            baseRedisService.removeAllOccurrences("blackList_" + black.getBlockedPhoneId(), black.getBlockerPhoneId());
        }
        int deleted = lifeBlacklistMapper.deleteById(black.getId());
        // DB 删除成功后，尽力同步推荐 feeds（动态+打卡）；失败不改变返回值
        if (deleted > 0) {
            // 与拉黑入库一致：仅用户拉黑商户时维护两片推荐 Redis
            try {
                tryPatchDynamicsRecommendBlockedStoresAfterUnblack(black);
            } catch (Exception e) {
                log.error("推荐 feeds 缓存同步失败(取消拉黑，动态+打卡)，不影响主流程 blockerId={} blockedId={}",
                        black.getBlockerId(), black.getBlockedId(), e);
            }
        }
        return deleted;
    }

    @Override
    public boolean hasBlackList(String otherSidePhoneId) throws Exception {
        try {
            String phoneId = Objects.requireNonNull(JwtUtil.getCurrentUserInfo()).getString("userType") + "_" + JwtUtil.getCurrentUserInfo().getString("phone");
            LambdaQueryWrapper<LifeBlacklist> wrapper = new LambdaQueryWrapper<>();
            wrapper.apply("((blocker_phone_id='" + otherSidePhoneId + "' and blocked_phone_id='" + phoneId + "')" +
                    " or (blocker_phone_id='" + phoneId + "' and blocked_phone_id='" + otherSidePhoneId + "'))");
            return lifeBlacklistMapper.selectCount(wrapper) > 0;
        } catch (Exception e) {
            log.error("LifeBlacklistServiceImpl.hasBlackList() error={}", e.getMessage());
            throw new Exception(e);
        }
    }

    /**
     * 是否要把拉黑关系同步到推荐 Redis（动态 {@code dynamics:recommend:v15:*} + 打卡 {@code clock_in:recommend:v15:*}）。
     * <p>
     * 仅当 <strong>C 端用户拉黑商户</strong> 时返回 true：{@code blocker_type=2} 且 {@code blocked_type=1}。
     * 拉黑用户、商户拉黑用户/商户等场景均返回 false，不写推荐缓存。
     * </p>
     */
    private static boolean shouldSyncDynamicsRecommendFeedBlacklist(LifeBlacklist row) {
        return row != null
                && "2".equals(row.getBlockerType())
                && "1".equals(row.getBlockedType());
    }

    /**
     * 用户拉黑商户：同步动态与打卡推荐缓存中的 {@code blocked_id}（store_user.id）。
     */
    private void tryPatchDynamicsRecommendBlockedStoresAfterBlack(LifeBlacklist row) {
        if (!shouldSyncDynamicsRecommendFeedBlacklist(row)) {
            return;
        }
        int viewerLifeUserId = Integer.parseInt(row.getBlockerId().trim());
        int blockedStoreUserId = Integer.parseInt(row.getBlockedId().trim());
        StoreUser su = storeUserMapper.selectById(blockedStoreUserId);
        if (su != null) {
            dynamicsRecommendCacheService.addBlockedStore(viewerLifeUserId, blockedStoreUserId);
            clockInRecommendCacheService.addBlockedStore(viewerLifeUserId, blockedStoreUserId);
        }
    }

    private void tryPatchDynamicsRecommendBlockedStoresAfterUnblack(LifeBlacklist row) {
        if (!shouldSyncDynamicsRecommendFeedBlacklist(row)) {
            return;
        }
        int viewerLifeUserId = Integer.parseInt(row.getBlockerId().trim());
        int blockedStoreUserId = Integer.parseInt(row.getBlockedId().trim());
        StoreUser su = storeUserMapper.selectById(blockedStoreUserId);
        if (su != null) {
            dynamicsRecommendCacheService.removeBlockedStore(viewerLifeUserId, blockedStoreUserId);
            clockInRecommendCacheService.removeBlockedStore(viewerLifeUserId, blockedStoreUserId);
        }
    }


}
