package shop.alien.store.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.alien.entity.store.*;
import shop.alien.entity.store.vo.StoreClockInVo;
import shop.alien.entity.store.vo.WebSocketVo;
import shop.alien.mapper.*;
import shop.alien.store.config.WebSocketProcess;
import shop.alien.store.service.CommonCommentService;
import shop.alien.store.service.StoreClockInService;
import shop.alien.store.service.StoreCommentService;
import shop.alien.store.util.ai.AiContentModerationUtil;
import shop.alien.util.common.constant.CommentSourceTypeEnum;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 店铺打卡 服务实现类
 * </p>
 *
 * @author ssk
 * @since 2025-05-15
 */
@Slf4j
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = Exception.class)
public class StoreClockInServiceImpl extends ServiceImpl<StoreClockInMapper, StoreClockIn> implements StoreClockInService {

    // 1. 自定义图片审核线程池（全局复用，避免频繁创建线程）
    private ExecutorService imgAuditExecutor;

    private final StoreClockInMapper storeClockInMapper;

    private final LifeUserMapper lifeUserMapper;

    private final LifeFansMapper lifeFansMapper;

    private final LifeLikeRecordMapper lifeLikeRecordMapper;

    private final StoreCommentService storeCommentService;

    private final LifeCollectMapper lifeCollectMapper;

    private final StoreInfoMapper storeInfoMapper;

     private final StoreImgMapper storeImgMapper;

    private final AiContentModerationUtil aiContentModerationUtil;

    private final LifeNoticeMapper lifeNoticeMapper;

    private final CommonCommentService commonCommentService;

    private final WebSocketProcess webSocketProcess;

    // 初始化线程池
    @PostConstruct
    public void initExecutor() {
        // 核心参数根据业务调整，IO密集型任务线程数可设为CPU核心数*2~4
        int corePoolSize = Runtime.getRuntime().availableProcessors() * 2;
        int maxPoolSize = Runtime.getRuntime().availableProcessors() * 4;
        imgAuditExecutor = new ThreadPoolExecutor(
                corePoolSize,
                maxPoolSize,
                60L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(500), // 任务队列，避免无界队列溢出
                new ThreadFactory() {
                    private int count = 0;
                    @Override
                    public Thread newThread(Runnable r) {
                        Thread t = new Thread(r);
                        t.setName("img-audit-" + count++); // 自定义线程名，便于排查
                        return t;
                    }
                },
                // 任务拒绝策略：记录日志+调用者线程兜底（避免任务丢失）
                new ThreadPoolExecutor.CallerRunsPolicy() {
                    @Override
                    public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                        log.error("图片审核任务被拒绝，队列已满！当前队列大小：{}，活跃线程数：{}",
                                e.getQueue().size(), e.getActiveCount());
                        super.rejectedExecution(r, e);
                    }
                }
        );

    }

    // 优雅关闭线程池
    @PreDestroy
    public void destroyExecutor() {
        if (Objects.nonNull(imgAuditExecutor)) {
            imgAuditExecutor.shutdown();
            try {
                if (!imgAuditExecutor.awaitTermination(30, TimeUnit.SECONDS)) {
                    imgAuditExecutor.shutdownNow();
                }
            } catch (InterruptedException e) {
                imgAuditExecutor.shutdownNow();
                Thread.currentThread().interrupt();
            }
        }
    }

    @Override
    public StoreClockIn addStoreClockIn(StoreClockIn storeClockIn) {
        LifeUser user = lifeUserMapper.selectById(storeClockIn.getUserId());
        storeClockIn.setPhoneId("user_" + user.getUserPhone());
        storeClockInMapper.insert(storeClockIn);
        return storeClockIn;
    }

    @Override
    public IPage<StoreClockInVo> getStoreClockInList(Integer userId, int page, int size, String phoneId, int mySelf,Integer storeId) {
        IPage<StoreClockIn> iPage = new Page<>(page, size);
        // 查询我的点赞
        LambdaQueryWrapper<LifeLikeRecord> likeWrapper = new LambdaQueryWrapper<>();
        likeWrapper.eq(LifeLikeRecord::getDianzanId, phoneId);
        likeWrapper.eq(LifeLikeRecord::getType, "5");
        List<LifeLikeRecord> lifeLikeList = lifeLikeRecordMapper.selectList(likeWrapper);
        List<String> likeList = lifeLikeList.stream().map(LifeLikeRecord::getHuifuId).collect(Collectors.toList());


        if(StringUtils.isNotBlank(String.valueOf(storeId)) && !String.valueOf(storeId).equals("null")){
            IPage<StoreClockInVo> storeClockInIPage1 = storeClockInMapper.getStoreClockInList(iPage, new QueryWrapper<StoreClockIn>()
                    .eq("clock.store_id", storeId)
                    .eq("clock.delete_flag", 0)
                    .ne("clock.check_flag", 3)
                    .eq("user.delete_flag", 0)
                    .eq("store.delete_flag", 0)
                    .isNotNull(0 == mySelf, "clock.img_url")
                    .and(wrapper1 ->
                            wrapper1.eq("clock.permission", 1)
                                    .or(wSub ->
                                            wSub.eq("clock.permission", 2)
                                                    .eq("clock.user_id", userId)
                                    ))
                    .orderByDesc("created_time"));
            storeClockInIPage1.getRecords().forEach(vo -> {
                if (likeList.contains(String.valueOf(vo.getId()))) {
                    vo.setIsLike("1");
                } else {
                    vo.setIsLike("0");
                }
            });
            return storeClockInIPage1;
        }
        QueryWrapper<StoreClockIn> wrapper = new QueryWrapper<>();
        wrapper.eq(1 == mySelf, "clock.user_id", userId);
        wrapper.isNotNull(0 == mySelf, "clock.img_url");
        wrapper.eq("clock.delete_flag", 0);
        wrapper.ne("clock.check_flag", 3);
        wrapper.eq("user.delete_flag", 0);
        wrapper.eq("store.delete_flag", 0);
        wrapper.and(wrapper1 ->
                wrapper1.eq("clock.permission", 1)
                        .or(wSub ->
                                wSub.eq("clock.permission", 2)
                                        .eq("clock.user_id", userId)
                        )
        );
        wrapper.orderByDesc("clock.created_time");

        IPage<StoreClockInVo> storeClockInIPage = storeClockInMapper.getStoreClockInList(iPage, wrapper);

        // 查询我的关注
        LambdaQueryWrapper<LifeFans> lifeFansWrapper = new LambdaQueryWrapper<>();
        lifeFansWrapper.eq(LifeFans::getFansId, phoneId);
        List<LifeFans> lifeFansList = lifeFansMapper.selectList(lifeFansWrapper);
        List<String> followList = lifeFansList.stream().map(LifeFans::getFollowedId).collect(Collectors.toList());

        // 查询我的粉丝
        lifeFansWrapper = new LambdaQueryWrapper<>();
        lifeFansWrapper.eq(LifeFans::getFollowedId, phoneId);
        lifeFansList = lifeFansMapper.selectList(lifeFansWrapper);
        List<String> fansList = lifeFansList.stream().map(LifeFans::getFansId).collect(Collectors.toList());



        // 查询我的收藏
        LambdaQueryWrapper<LifeCollect> collectWrapper = new LambdaQueryWrapper<>();
        collectWrapper.eq(LifeCollect::getUserId, String.valueOf(userId));
        List<LifeCollect> lifeCollectList = lifeCollectMapper.selectList(collectWrapper);
        List<String> collectList = lifeCollectList.stream().map(LifeCollect::getStoreId).collect(Collectors.toList());


        storeClockInIPage.getRecords().forEach(vo -> {
            if (followList.contains(vo.getPhoneId())) {
                vo.setIsFollowThis("1");
            } else {
                vo.setIsFollowThis("0");
            }
            if (fansList.contains(vo.getPhoneId())) {
                vo.setIsFollowMe("1");
            } else {
                vo.setIsFollowMe("0");
            }
            if (likeList.contains(String.valueOf(vo.getId()))) {
                vo.setIsLike("1");
            } else {
                vo.setIsLike("0");
            }
            if (collectList.contains(String.valueOf(vo.getStoreId()))) {
                vo.setIsCollect("1");
            } else {
                vo.setIsCollect("0");
            }

//            // 该用户的打卡记录
//            LambdaQueryWrapper<StoreClockIn> clockInWrapper = new LambdaQueryWrapper<>();
//            clockInWrapper.eq(StoreClockIn::getUserId, vo.getUserId());
//            List<StoreClockIn> clockInList = storeClockInMapper.selectList(clockInWrapper);
//
//            Set<Integer> clockInSet = clockInList.stream().map(StoreClockIn::getStoreId).collect(Collectors.toSet());
//            // 该用户今天打卡记录
//            Set<Integer> clockInTodaySet = clockInList.stream().filter(item -> item.getCreatedTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate().equals(LocalDate.now())).map(StoreClockIn::getStoreId).collect(Collectors.toSet());
//
//            // 在该店铺的打卡次数
//            Map<Integer, Long> clockInStoreNumMap = clockInList.stream().collect(Collectors.groupingBy(StoreClockIn::getStoreId, Collectors.counting()));
//
//            // 该用户打卡的所有店铺次数（一个店铺只算一次）
//            int clockInNum = (int) clockInList.stream().map(StoreClockIn::getStoreId).distinct().count();
//
//            // 是否在该店铺打过卡
//            if (clockInSet.contains(vo.getStoreId())){
//                vo.setClockInStore("1");
//            } else {
//                vo.setClockInStore("0");
//            }
//            // 今天是否在该店铺打过卡
//            if (clockInTodaySet.contains(vo.getStoreId())){
//                vo.setClockInStoreToday("1");
//            } else {
//                vo.setClockInStoreToday("0");
//            }
//            // 在该店铺打卡次数clockInStoreNum
//            vo.setClockInStoreNum(clockInStoreNumMap.get(vo.getStoreId()));
//            // 打卡次数
//            vo.setClockInNum(clockInNum);
            Map<String, Object> commitCount = commonCommentService.getCommitCount(vo.getId(), CommentSourceTypeEnum.CLOCK_IN_COMMENT.getType(), userId.toString(), null);
            vo.setCommentCount(Integer.parseInt(commitCount.get("commentCount").toString()));
            if(Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗").contains(vo.getBusinessSectionName())){
                vo.setStoreTypeNew(1);
            } else if (Arrays.asList("丽人美发", "运动健身").contains(vo.getBusinessSectionName())){
                vo.setStoreTypeNew(2);
            } else if (Arrays.asList("特色美食").contains(vo.getBusinessSectionName())){
                vo.setStoreTypeNew(3);
            }
        });


        return storeClockInIPage;
    }

    @Override
    public int deleteClockIn(Integer id) {
        return storeClockInMapper.deleteById(id);
    }

    @Override
    public int setPermission(int userId, Integer id, int permission) {
        LambdaUpdateWrapper<StoreClockIn> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(StoreClockIn::getPermission, permission);
        wrapper.eq(StoreClockIn::getUserId, userId);
        wrapper.eq(null != id, StoreClockIn::getId, id);
        return storeClockInMapper.update(null, wrapper);
    }

    @Override
    public int setImgAndAiContent(int id, String img,String aiContent) {
        // 1. 先更新打卡状态为"审核中"，然后返回
        LambdaUpdateWrapper<StoreClockIn> wrapper = new LambdaUpdateWrapper<>();
        wrapper.set(StoreClockIn::getImgUrl, img);
        wrapper.set(StoreClockIn::getMaybeAiContent, aiContent);
        wrapper.set(StoreClockIn::getCheckFlag, 1); // 1-审核中
        wrapper.eq(StoreClockIn::getId, id);
        int updateResult = storeClockInMapper.update(null, wrapper);
        
        // 2. 异步调用AI接口审核图片
        StoreClockIn storeClockIn = storeClockInMapper.selectById(id);
        if (storeClockIn == null) {
            log.warn("打卡记录不存在，id={}", id);
            return updateResult;
        }
        
        LifeUser lifeUser = lifeUserMapper.selectById(storeClockIn.getUserId());
        if (lifeUser == null) {
            log.warn("用户不存在，userId={}", storeClockIn.getUserId());
            return updateResult;
        }
        
        final String phoneId = "user_" + lifeUser.getUserPhone();
        final Integer clockInId = id;
        final Integer userId = storeClockIn.getUserId();
        
        List<String> imgList = new ArrayList<>();
        if (StringUtils.isNotBlank(img)) {
            String[] imgArray = img.split(",");
            for (String imgUrl : imgArray) {
                String trimmed = imgUrl.trim();
                if (StringUtils.isNotBlank(trimmed)) {
                    imgList.add(trimmed);
                }
            }
        }
        
        // 异步执行AI审核任务
        CompletableFuture.runAsync(() -> {
            AiContentModerationUtil.AuditResult imgAuditResult = null;
            try {
                imgAuditResult = CompletableFuture.supplyAsync(
                        () -> aiContentModerationUtil.auditContent(null, imgList),
                        imgAuditExecutor
                ).get();

                // 3. 审核后按照注释修改状态
                LambdaUpdateWrapper<StoreClockIn> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(StoreClockIn::getId, clockInId);
                
                if (imgAuditResult != null && imgAuditResult.isPassed()) {
                    // 审核通过,修改状态,打卡可显示在列表中
                    updateWrapper.set(StoreClockIn::getCheckFlag, 2); // 2-审核通过
                    updateWrapper.set(StoreClockIn::getReason, null); // 清除拒绝原因
                    storeClockInMapper.update(null, updateWrapper);
                    log.info("打卡图片审核通过，打卡ID：{}", clockInId);
                } else {
                    // 审核拒绝,修改状态,打卡不可显示在列表中,通知用户,打卡审核不通过
                    String rejectReason = (imgAuditResult != null && StringUtils.isNotEmpty(imgAuditResult.getFailureReason()))
                            ? imgAuditResult.getFailureReason()
                            : "图片内容不符合规范";
                    updateWrapper.set(StoreClockIn::getCheckFlag, 3); // 2-审核完成（但审核未通过）
                    updateWrapper.set(StoreClockIn::getReason, rejectReason); // 记录拒绝原因
                    storeClockInMapper.update(null, updateWrapper);
                    log.warn("打卡图片审核拒绝，打卡ID：{}，原因：{}", clockInId, rejectReason);
                    
                    // 通知用户打卡审核不通过
                    sendAuditRejectNotification(clockInId, userId, phoneId, rejectReason);
                }
            } catch (Exception e) {
                log.error("图片审核接口调用异常，打卡ID：{}", clockInId, e);
                // 审核异常时，保持审核中状态，记录错误原因
                LambdaUpdateWrapper<StoreClockIn> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(StoreClockIn::getId, clockInId);
                updateWrapper.set(StoreClockIn::getCheckFlag, 1); // 保持审核中状态
                updateWrapper.set(StoreClockIn::getReason, "审核异常，请稍后重试");
                storeClockInMapper.update(null, updateWrapper);
            }
        }, imgAuditExecutor);
        
        return updateResult;
    }

    /**
     * 发送审核拒绝通知
     *
     * @param clockInId 打卡ID
     * @param userId    用户ID
     * @param phoneId   用户phoneId
     * @param reason    拒绝原因
     */
    private void sendAuditRejectNotification(Integer clockInId, Integer userId, String phoneId, String reason) {
        try {
            LifeNotice lifeNotice = new LifeNotice();
            lifeNotice.setSenderId("system");
            lifeNotice.setBusinessId(clockInId);
            lifeNotice.setReceiverId(phoneId);
            lifeNotice.setTitle("打卡审核通知");
            lifeNotice.setNoticeType(1); // 1-系统通知
            lifeNotice.setIsRead(0);

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("message", "您的打卡审核未通过，原因：" + reason);
            jsonObject.put("clockInId", clockInId);
            jsonObject.put("status", "rejected");
            lifeNotice.setContext(jsonObject.toJSONString());

            // 保存通知
            lifeNoticeMapper.insert(lifeNotice);

            // 发送WebSocket消息
            WebSocketVo webSocketVo = new WebSocketVo();
            webSocketVo.setSenderId("system");
            webSocketVo.setReceiverId(phoneId);
            webSocketVo.setCategory("notice");
            webSocketVo.setNoticeType("1");
            webSocketVo.setIsRead(0);
            webSocketVo.setText(JSONObject.from(lifeNotice).toJSONString());
            webSocketProcess.sendMessage(phoneId, JSONObject.from(webSocketVo).toJSONString());

            log.info("打卡审核拒绝通知发送成功，打卡ID：{}，接收人：{}", clockInId, phoneId);
        } catch (Exception e) {
            log.error("发送打卡审核拒绝通知失败，打卡ID：{}，异常信息：{}", clockInId, e.getMessage(), e);
        }
    }

    /**
     * 获取门店打卡次数
     *
     * @return list
     */
    @Override
    public List<Map<Integer, Integer>> getStoreClockInCount() {
        return storeClockInMapper.getStoreClockInCount();
    }

    /**
     * 获取所有店铺打卡次数（有图片并且设置为可见的）
     *
     * @return map
     */
    @Override
    public List<Map<Integer, Integer>> getStoreClockInWithCanLookCount() {
        return storeClockInMapper.getStoreClockInWithCanLookCount();
    }

    @Override
    public StoreClockInVo getStoreClockInById(Integer id, Integer userId) {
        StoreClockIn storeClockIn = storeClockInMapper.selectById(id);
        StoreClockInVo storeClockInVo = BeanUtil.copyProperties(storeClockIn, StoreClockInVo.class);
        if (null == storeClockIn) {
            return null;
        }

        StoreInfo storeInfo = storeInfoMapper.selectById(storeClockIn.getStoreId());
        // 店铺名称
        storeClockInVo.setStoreName(storeInfo.getStoreName());
        // 店铺头像
        LambdaQueryWrapper<StoreImg> eq = new LambdaQueryWrapper<StoreImg>().eq(StoreImg::getImgType, 10).eq(StoreImg::getStoreId, storeInfo.getId());
        StoreImg storeImg = storeImgMapper.selectOne(eq);
        storeClockInVo.setEntranceImage(storeImg != null ? storeImg.getImgUrl() : "");
        // 店铺评分
        storeClockInVo.setScore(storeInfo.getScoreAvg());
        // 设置店铺大类
        String businessSectionName = storeInfo.getBusinessSectionName();
        if(Arrays.asList("酒吧", "KTV", "洗浴汗蒸", "按摩足疗").contains(businessSectionName)){
            storeClockInVo.setStoreTypeNew(1);
        } else if (Arrays.asList("丽人美发", "运动健身").contains(businessSectionName)){
            storeClockInVo.setStoreTypeNew(2);
        } else if (Arrays.asList("特色美食").contains(businessSectionName)){
            storeClockInVo.setStoreTypeNew(3);
        }
        // 最小分类
        storeClockInVo.setBusinessClassifyName(storeInfo.getBusinessClassifyName());
        // 地址
        storeClockInVo.setStoreAddress(storeInfo.getStoreAddress());
        // 是否收藏 - 使用当前登录用户的ID查询收藏
        storeClockInVo.setIsCollect("0");
        if (userId != null) {
            LambdaQueryWrapper<LifeCollect> collectWrapper = new LambdaQueryWrapper<>();
            collectWrapper.eq(LifeCollect::getUserId, String.valueOf(userId));
            List<LifeCollect> lifeCollectList = lifeCollectMapper.selectList(collectWrapper);
            List<String> collectList = lifeCollectList.stream().map(LifeCollect::getStoreId).collect(Collectors.toList());
            if (collectList.contains(storeClockInVo.getStoreId().toString())){
                storeClockInVo.setIsCollect("1");
            }
        }
        return storeClockInVo;
    }
}
