package com.ruoyi.wx.web.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.WxUser;
import com.ruoyi.common.core.domain.model.LoginWxUser;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.recovery.domain.RecContent;
import com.ruoyi.framework.recovery.domain.RecContentUser;
import com.ruoyi.framework.recovery.domain.RecSaleInfo;
import com.ruoyi.framework.recovery.domain.RecStores;
import com.ruoyi.framework.recovery.domain.vo.WxContent;
import com.ruoyi.framework.recovery.mapper.RecContentMapper;
import com.ruoyi.framework.recovery.mapper.RecSaleInfoMapper;
import com.ruoyi.framework.recovery.service.IRecContentService;
import com.ruoyi.framework.recovery.service.IRecSaleInfoService;
import com.ruoyi.wx.web.domain.dto.WxContentDto;
import com.ruoyi.wx.web.domain.vo.RecStoresVo;
import com.ruoyi.wx.web.domain.vo.SaleInfoVo;
import com.ruoyi.wx.web.domain.vo.WxContentVo;
import com.ruoyi.wx.web.mapper.WxHomeMapper;
import com.ruoyi.wx.web.service.IWxHomeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class WxHomeServiceImpl implements IWxHomeService {
    @Autowired
    private IRecSaleInfoService recSaleInfoService;

    @Autowired
    private IRecContentService recContentService;

    @Autowired
    private RecSaleInfoMapper saleInfoMapper;

    @Autowired
    private WxHomeMapper wxHomeMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private RecContentMapper recContentMapper;

    private final static ArrayBlockingQueue<Runnable> WORK_QUEUE = new ArrayBlockingQueue<>(9);

    private final static RejectedExecutionHandler HANDLER = new ThreadPoolExecutor.CallerRunsPolicy();

    @SuppressWarnings("unused")
    private static ThreadPoolExecutor executorService = new ThreadPoolExecutor(9, 9, 1000, TimeUnit.MILLISECONDS,
            WORK_QUEUE, HANDLER);

    @Override
    public AjaxResult getIndex() throws ExecutionException, InterruptedException {
        LoginWxUser loginWxUser = null;
        try {
            loginWxUser = SecurityUtils.getLoginWxUser();
        } catch (ServiceException e) {
            log.error("用户未登录");
        }
        // 查询最近创建的活动并且处于活动期间的内容
        DateTime dateTime = DateUtil.beginOfDay(new Date());
        Date startTime = DateUtil.offsetDay(dateTime, -1);
        Date endTime = DateUtil.offsetDay(dateTime, 1);
        Callable<List<RecSaleInfo>> saleInfoCallable = () -> recSaleInfoService.selectRecSaleInfoByTime(startTime, endTime);
        // 评论
        Callable<List<WxContent>> contentCallable = null;
        if (BeanUtil.isEmpty(loginWxUser)) {
            contentCallable = () -> recContentService.selectWxContentList(new WxContent());
        } else {
            LoginWxUser finalLoginWxUser = loginWxUser;
            contentCallable = () -> recContentService.selectRecContentByOpenId(finalLoginWxUser.getWxUser().getWxOpenid());
        }
        FutureTask<List<RecSaleInfo>> saleInfoTask = new FutureTask<>(saleInfoCallable);
        FutureTask<List<WxContent>> contentTask = new FutureTask<>(contentCallable);
        executorService.submit(saleInfoTask);
        executorService.submit(contentTask);
        List<WxContent> contents = contentTask.get();
        List<WxContentVo> contentVos = new ArrayList<>();
        for (WxContent content : contents) {
            String images = content.getImages();
            WxContentVo vo = new WxContentVo();
            BeanUtils.copyProperties(content, vo);
            if (StringUtils.isNotEmpty(images)) {
                List<String> imagesList = Arrays.asList(images.split(","));
                vo.setImageList(imagesList);
            }
            contentVos.add(vo);
        }
        String display = wxHomeMapper.selectLotteryDisplay("is_lottery");
        List<RecSaleInfo> saleInfos = saleInfoTask.get();
//        saleInfos.sort(Comparator.comparing(RecSaleInfo::getTopIndex, Integer::compareTo));
        contentVos.sort(Comparator.comparing(WxContentVo::getCreateDate, Comparator.reverseOrder()));
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("saleInfo", saleInfos);
        resultMap.put("content", contentVos);
        resultMap.put("is_lottery", display);
        return AjaxResult.success(resultMap);
    }

    @Override
    public List<SaleInfoVo> getSaleInfo(Long id, String storeIds) {
        RecSaleInfo saleInfo = saleInfoMapper.selectRecSaleInfoById(id);
        // 根据商品获取所有门店信息
        List<RecStores> stores = wxHomeMapper.selectRecStoresByCommondityIds(storeIds);
        Map<String, List<RecStores>> cityMap = stores.stream().filter(vo -> StringUtils.isNotEmpty(vo.getCity())).collect(Collectors.groupingBy(RecStores::getCity));
        List<SaleInfoVo> result = new ArrayList<>();
        SaleInfoVo saleInfoVo = new SaleInfoVo();
        List<RecStoresVo> cityList = new ArrayList<>();
        BeanUtils.copyProperties(saleInfo, saleInfoVo);
        // 插入门店详情
        cityMap.forEach((key, value) -> {
            RecStoresVo storesVo = new RecStoresVo();
            storesVo.setCity(key);
            storesVo.setStores(value);
            cityList.add(storesVo);
        });
        saleInfoVo.setStores(cityList);
        result.add(saleInfoVo);
        log.info("查询发售信息详情结束");
        return result;
    }

    @Override
    public List<SaleInfoVo> getSaleCalendar() {
        RecSaleInfo saleInfo = new RecSaleInfo();
        saleInfo.setEndTimeOfActivity(LocalDateTime.now(ZoneId.of("Asia/Shanghai")));
        List<RecSaleInfo> recSaleInfos = saleInfoMapper.selectRecSaleInfoList(saleInfo);
        List<SaleInfoVo> result = new ArrayList<>();
        for (RecSaleInfo info : recSaleInfos) {
            SaleInfoVo vo = new SaleInfoVo();
            BeanUtils.copyProperties(info, vo);
            vo.setStore(belongCalendar(LocalDateTime.now(ZoneId.of("Asia/Shanghai")), vo.getEventStartTime(), vo.getEndTimeOfActivity()));
            result.add(vo);
        }
        result.sort(Comparator.comparing(SaleInfoVo::getEndTimeOfActivity));
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long thumbs(Long id) {
        // 点赞记录
        LoginWxUser loginWxUser = SecurityUtils.getLoginWxUser();
        if (loginWxUser == null) {
            throw new SecurityException("请登录");
        }
        WxUser wxUser = loginWxUser.getWxUser();
        List<RecContentUser> contentUser = recContentMapper.selectContentUserByOpenId(wxUser.getWxOpenid(), id);
        if (CollectionUtil.isNotEmpty(contentUser)) {
            throw new RuntimeException("该用户已点过赞");
        }
        int count = recContentService.insertRecContentUser(wxUser.getWxOpenid(), id);
        // 点赞数加一
        RecContent content = recContentService.selectRecContentById(id);
        content.setThumbs(content.getThumbs() + 1);
        recContentService.updateRecContent(content);
        return (long) count;
    }

    @Override
    public int addRecContent(WxContentDto dto) {
        List<String> images = dto.getImageList();
        String image = images.stream().map(String::valueOf).collect(Collectors.joining(","));
        RecContent content = new RecContent();
        BeanUtils.copyProperties(dto, content);
        content.setImages(image);
        content.setCreateDate(LocalDateTime.now(ZoneId.of("Asia/Shanghai")));
        return recContentMapper.insertRecContent(content);
    }

    @Override
    public List<RecContentUser> userThumbs() {
        LoginWxUser loginWxUser = SecurityUtils.getLoginWxUser();
        if (loginWxUser == null) {
            throw new SecurityException("请登录");
        }
        WxUser wxUser = loginWxUser.getWxUser();
        return recContentMapper.selectContentUserByOpenId(wxUser.getWxOpenid(), null);
    }

    /**
     * 将字符串转日期成Long类型的时间戳，格式为：yyyy-MM-dd HH:mm:ss
     */
    public static Long convertTimeToLong(String time) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime parse = LocalDateTime.parse(time, formatter);
        return LocalDateTime.from(parse).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    /**
     * 判断时间是否在时间段内
     *
     * @param nowTime
     * @param beginTime
     * @param endTime
     * @return
     */
    public static boolean belongCalendar(LocalDateTime nowTime, LocalDateTime beginTime, LocalDateTime endTime) {
        log.info("当前时间：{}, 开始时间:{}, 结束时间:{}", nowTime, beginTime, endTime);
        return nowTime.isAfter(beginTime) && nowTime.isBefore(endTime);
    }
}
