package shop.alien.second.task;

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 lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import shop.alien.config.redis.BaseRedisService;
import shop.alien.entity.second.SecondGoods;
import shop.alien.entity.second.SecondTradeOperation;
import shop.alien.entity.second.SecondTradeRecord;
import shop.alien.entity.store.LifeMessage;
import shop.alien.entity.store.LifeNotice;
import shop.alien.entity.store.LifeUser;
import shop.alien.entity.store.vo.WebSocketVo;
import shop.alien.mapper.LifeMessageMapper;
import shop.alien.mapper.LifeNoticeMapper;
import shop.alien.mapper.LifeUserMapper;
import shop.alien.mapper.second.SecondGoodsMapper;
import shop.alien.mapper.second.SecondTradeOperationMapper;
import shop.alien.mapper.second.SecondTradeRecordMapper;
import shop.alien.second.feign.AlienStoreFeign;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Component
@RequiredArgsConstructor
public class Task {

    private final SecondTradeRecordMapper secondTradeRecordMapper;

    private final LifeNoticeMapper lifeNoticeMapper;

    private final LifeUserMapper lifeUserMapper;

    private final LifeMessageMapper lifeMessageMapper;

    private final AlienStoreFeign alienStoreFeign;

    private final BaseRedisService baseRedisService;

    private final SecondGoodsMapper secondGoodsMapper;

    private final SecondTradeOperationMapper secondTradeOperationMapper;

    @Value("${ScheduledTask.enabled}")
    private boolean isEnable;

    /**
     * 二手交易平台 - 交易时间前的十分钟之前  给买家和卖家发送通知提醒
     */
    @Scheduled(cron = "0 * * * * ?")
    public void secondTradeRemind() throws Exception {
        if (!isEnable) {
            return;
        }

        log.info("开始执行定时任务： 二手交易平台 - 10分钟后交易提醒 - secondTradeRemind");
        try {
            Date tenMinuteLater = Date.from(LocalDateTime.now().plusMinutes(10).withSecond(0).withNano(0).atZone(ZoneId.systemDefault()).toInstant());

            // 查询所有待交易
            LambdaQueryWrapper<SecondTradeRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SecondTradeRecord::getTradeStatus, 3);
            wrapper.eq(SecondTradeRecord::getTransactionTime, tenMinuteLater);
            List<SecondTradeRecord> tradeRecordList = secondTradeRecordMapper.selectList(wrapper);

            for (SecondTradeRecord tradeRecord : tradeRecordList) {
                LifeUser buyer = lifeUserMapper.selectById(tradeRecord.getBuyerId());
                LifeUser seller = lifeUserMapper.selectById(tradeRecord.getSellerId());

                String buyerPhoneId = null == buyer ? "" : "user_" + buyer.getUserPhone();
                String sellerPhoneId = null == seller ? "" : "user_" + seller.getUserPhone();

                // 封装交易信息
                JSONObject message = new JSONObject();
                message.put("tradeId", tradeRecord.getId());
                message.put("transactionAmount", tradeRecord.getTransactionAmount());
                message.put("transactionLatitudeLongitude", tradeRecord.getTransactionLatitudeLongitude());
                message.put("transactionLatitudeLongitudeAddress", tradeRecord.getTransactionLatitudeLongitudeAddress());
                message.put("transactionLocation", tradeRecord.getTransactionLocation());
                message.put("transactionTime", tradeRecord.getTransactionTime());
                message.put("tradeStatus", tradeRecord.getTradeStatus());

                // 给买家发送消息
                LifeMessage lifeMessage = new LifeMessage();
                lifeMessage.setSenderId(sellerPhoneId);
                lifeMessage.setReceiverId(buyerPhoneId);
                lifeMessage.setContent(message.toJSONString());
                lifeMessage.setType("5");
                lifeMessageMapper.insert(lifeMessage);

                // 给买家推送消息
                WebSocketVo webSocketVo = new WebSocketVo();
                webSocketVo.setSenderId(sellerPhoneId);
                webSocketVo.setReceiverId(buyerPhoneId);
                webSocketVo.setCategory("message");
                webSocketVo.setType("5");
                webSocketVo.setText(message.toJSONString());
                webSocketVo.setMessageId(lifeMessage.getId());
                alienStoreFeign.sendMsgToClientByPhoneId(buyerPhoneId, JSONObject.from(webSocketVo).toJSONString());

                // 给买家发送通知
                LifeNotice lifeNotice = new LifeNotice();
                lifeNotice.setSenderId("system");
                lifeNotice.setReceiverId(buyerPhoneId);
                lifeNotice.setBusinessId(tradeRecord.getId());
                lifeNotice.setTitle("商品交易签到");
                lifeNotice.setNoticeType(1);
                // 封装通知信息
                JSONObject noticeMessage = new JSONObject();
                noticeMessage.put("tradeId", tradeRecord.getId());
                noticeMessage.put("otherSideUserId", tradeRecord.getSellerId());
                noticeMessage.put("otherSidePhoneId", sellerPhoneId);
                noticeMessage.put("otherSideName", null == seller ? "" : seller.getUserName());
                noticeMessage.put("otherSideImage", null == seller ? "" : seller.getUserImage());
                noticeMessage.put("message", "您有一笔交易即将开始, 请及时前往查看");
                lifeNotice.setContext(noticeMessage.toJSONString());
                lifeNoticeMapper.insert(lifeNotice);

                // 给买家推送通知
                webSocketVo = new WebSocketVo();
                webSocketVo.setSenderId("system");
                webSocketVo.setReceiverId(buyerPhoneId);
                webSocketVo.setCategory("notice");
                webSocketVo.setNoticeType("1");
                webSocketVo.setType("5");
                webSocketVo.setText(JSONObject.from(lifeNotice).toJSONString());
                webSocketVo.setMessageId(lifeMessage.getId());
                alienStoreFeign.sendMsgToClientByPhoneId(buyerPhoneId, JSONObject.from(webSocketVo).toJSONString());

                // 给卖家发送消息
                lifeMessage = new LifeMessage();
                lifeMessage.setSenderId(buyerPhoneId);
                lifeMessage.setReceiverId(sellerPhoneId);
                lifeMessage.setContent(message.toJSONString());
                lifeMessage.setType("5");
                lifeMessageMapper.insert(lifeMessage);

                // 给卖家推送消息
                webSocketVo = new WebSocketVo();
                webSocketVo.setSenderId(buyerPhoneId);
                webSocketVo.setReceiverId(sellerPhoneId);
                webSocketVo.setCategory("message");
                webSocketVo.setType("5");
                webSocketVo.setText(message.toJSONString());
                webSocketVo.setMessageId(lifeMessage.getId());
                alienStoreFeign.sendMsgToClientByPhoneId(sellerPhoneId, JSONObject.from(webSocketVo).toJSONString());

                // 给卖家发送通知
                lifeNotice = new LifeNotice();
                lifeNotice.setSenderId("system");
                lifeNotice.setReceiverId(sellerPhoneId);
                lifeNotice.setBusinessId(tradeRecord.getId());
                lifeNotice.setTitle("商品交易签到");
                lifeNotice.setNoticeType(1);
                // 封装通知信息
                noticeMessage = new JSONObject();
                noticeMessage.put("tradeId", tradeRecord.getId());
                noticeMessage.put("otherSideUserId", tradeRecord.getBuyerId());
                noticeMessage.put("otherSidePhoneId", buyerPhoneId);
                noticeMessage.put("otherSideName", null == buyer ? "" : buyer.getUserName());
                noticeMessage.put("otherSideImage", null == buyer ? "" : buyer.getUserImage());
                noticeMessage.put("message", "您有一笔交易即将开始, 请及时前往查看");
                lifeNotice.setContext(noticeMessage.toJSONString());
                lifeNoticeMapper.insert(lifeNotice);

                // 给卖家推送通知
                webSocketVo = new WebSocketVo();
                webSocketVo.setSenderId("system");
                webSocketVo.setReceiverId(sellerPhoneId);
                webSocketVo.setCategory("notice");
                webSocketVo.setNoticeType("1");
                webSocketVo.setType("5");
                webSocketVo.setText(JSONObject.from(lifeNotice).toJSONString());
                webSocketVo.setMessageId(lifeMessage.getId());
                alienStoreFeign.sendMsgToClientByPhoneId(sellerPhoneId, JSONObject.from(webSocketVo).toJSONString());
            }
        } catch (Exception e) {
            log.error("SecondGoodsTradeXxlJob.secondTradeRemind Error Msg={}", e.getMessage());
        }
    }

    /**
     * 二手交易平台 - 到达交易时间时,给买家和卖家发送交易确认提醒
     */
    @Scheduled(cron = "0 * * * * ?")
    public void secondTradeConfirm() throws Exception {
        if (!isEnable) {
            return;
        }

        log.info("开始执行定时任务: 二手交易平台 - 到达交易时间时,给买家和卖家发送交易确认提醒 - secondTradeConfirm");
        try {
            Date now = Date.from(LocalDateTime.now().withSecond(0).withNano(0).atZone(ZoneId.systemDefault()).toInstant());

            // 查询所有待交易
            LambdaQueryWrapper<SecondTradeRecord> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(SecondTradeRecord::getTradeStatus, 3);
            wrapper.eq(SecondTradeRecord::getTransactionTime, now);
            List<SecondTradeRecord> tradeRecordList = secondTradeRecordMapper.selectList(wrapper);

            for (SecondTradeRecord tradeRecord : tradeRecordList) {
                LifeUser buyer = lifeUserMapper.selectById(tradeRecord.getBuyerId());
                LifeUser seller = lifeUserMapper.selectById(tradeRecord.getSellerId());
                SecondGoods goods = secondGoodsMapper.selectById(tradeRecord.getGoodsId());

                String buyerPhoneId = null == buyer ? "" : "user_" + buyer.getUserPhone();
                String sellerPhoneId = null == seller ? "" : "user_" + seller.getUserPhone();

                // 给买家发送通知
                LifeNotice lifeNotice = new LifeNotice();
                lifeNotice.setSenderId("system");
                lifeNotice.setReceiverId(buyerPhoneId);
                lifeNotice.setBusinessId(tradeRecord.getId());
                lifeNotice.setTitle("商品是否交易成功");
                lifeNotice.setNoticeType(1);
                // 封装通知信息
                JSONObject noticeMessage = new JSONObject();
                noticeMessage.put("goodsId", goods.getId());
                noticeMessage.put("goodsHomeImage", goods.getHomeImage());
                noticeMessage.put("goodsTitle", goods.getTitle());
                noticeMessage.put("tradeId", tradeRecord.getId());
                noticeMessage.put("transactionAmount", tradeRecord.getTransactionAmount());
                noticeMessage.put("transactionLatitudeLongitude", tradeRecord.getTransactionLatitudeLongitude());
                noticeMessage.put("transactionLatitudeLongitudeAddress", tradeRecord.getTransactionLatitudeLongitudeAddress());
                noticeMessage.put("transactionLocation", tradeRecord.getTransactionLocation());
                noticeMessage.put("transactionTime", tradeRecord.getTransactionTime());
                noticeMessage.put("tradeStatus", tradeRecord.getTradeStatus());
                noticeMessage.put("message", "您有一笔交易已完成, 请前往确认");
                lifeNotice.setContext(noticeMessage.toJSONString());
                lifeNoticeMapper.insert(lifeNotice);

                // 给买家推送通知
                WebSocketVo webSocketVo = new WebSocketVo();
                webSocketVo.setSenderId("system");
                webSocketVo.setReceiverId(buyerPhoneId);
                webSocketVo.setCategory("notice");
                webSocketVo.setNoticeType("1");
                webSocketVo.setType("5");
                webSocketVo.setIsRead(0);
                webSocketVo.setText(JSONObject.from(lifeNotice).toJSONString());
                alienStoreFeign.sendMsgToClientByPhoneId(buyerPhoneId, JSONObject.from(webSocketVo).toJSONString());

                // 给卖家发送通知
                lifeNotice = new LifeNotice();
                lifeNotice.setSenderId("system");
                lifeNotice.setReceiverId(sellerPhoneId);
                lifeNotice.setBusinessId(tradeRecord.getId());
                lifeNotice.setTitle("商品是否交易成功");
                lifeNotice.setNoticeType(1);
                lifeNotice.setContext(noticeMessage.toJSONString());
                lifeNoticeMapper.insert(lifeNotice);

                // 给卖家推送通知
                webSocketVo = new WebSocketVo();
                webSocketVo.setSenderId("system");
                webSocketVo.setReceiverId(sellerPhoneId);
                webSocketVo.setCategory("notice");
                webSocketVo.setNoticeType("1");
                webSocketVo.setType("5");
                webSocketVo.setIsRead(0);
                webSocketVo.setText(JSONObject.from(lifeNotice).toJSONString());
                alienStoreFeign.sendMsgToClientByPhoneId(sellerPhoneId, JSONObject.from(webSocketVo).toJSONString());
            }
        } catch (Exception e) {
            log.error("SecondGoodsTradeXxlJob.secondTradeConfirm Error Mgs={}", e.getMessage());
        }
    }

    /**
     * 二手交易平台 - 交易超时未确认则自动取消
     */
    @Scheduled(cron = "0 * * * * ?")
    private void secondTradeTimeoutCancel() {
        if (!isEnable) {
            return;
        }

        log.info("开始执行定时任务: 二手交易平台 - 交易超时未确认则自动取消 - secondTradeTimeoutCancel");
        try {
            Date now = Date.from(LocalDateTime.now().withSecond(0).withNano(0).atZone(ZoneId.systemDefault()).toInstant());

            // 查询所有待确认
            LambdaQueryWrapper<SecondTradeRecord> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SecondTradeRecord::getTradeStatus, 1);
            queryWrapper.eq(SecondTradeRecord::getTransactionTime, now);
            List<SecondTradeRecord> tradeRecordList = secondTradeRecordMapper.selectList(queryWrapper);
            List<Integer> tradeIdList = tradeRecordList.stream().map(SecondTradeRecord::getId).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(tradeIdList)) {
                LambdaUpdateWrapper<SecondTradeRecord> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.in(SecondTradeRecord::getId, tradeIdList)
                        .set(SecondTradeRecord::getTradeStatus, 6);
                secondTradeRecordMapper.update(null, updateWrapper);

                for (Integer id : tradeIdList) {
                    SecondTradeOperation operation = new SecondTradeOperation();
                    operation.setTradeId(id);
                    operation.setUserId(0);
                    operation.setType(7);
                    secondTradeOperationMapper.insert(operation);
                }
            }
        } catch (Exception e) {
            log.error("SecondGoodsTradeXxlJob.secondTradeTimeoutCancel Error Mgs={}", e.getMessage());
        }
    }

    /**
     * 二手交易平台 - 到达交易时间12个小时后,自动交易失败
     */
    @Scheduled(cron = "0 * * * * ?")
    private void secondTradeTimeoutFail() {
        if (!isEnable) {
            return;
        }

        log.info("开始执行定时任务: 二手交易平台 - 到达交易时间12个小时后,自动交易失败 - secondTradeTimeoutFail");
        try {
            Date twelveBefore = Date.from(LocalDateTime.now().plusHours(12).withSecond(0).withNano(0).atZone(ZoneId.systemDefault()).toInstant());

            // 查询所有待确认
            LambdaQueryWrapper<SecondTradeRecord> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SecondTradeRecord::getTradeStatus, 3);
            queryWrapper.eq(SecondTradeRecord::getTransactionTime, twelveBefore);
            List<SecondTradeRecord> tradeRecordList = secondTradeRecordMapper.selectList(queryWrapper);
            List<Integer> tradeIdList = tradeRecordList.stream().map(SecondTradeRecord::getId).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(tradeIdList)) {
                LambdaUpdateWrapper<SecondTradeRecord> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.in(SecondTradeRecord::getId, tradeIdList)
                        .set(SecondTradeRecord::getTradeStatus, 5);
                secondTradeRecordMapper.update(null, updateWrapper);

                for (Integer id : tradeIdList) {
                    SecondTradeOperation operation = new SecondTradeOperation();
                    operation.setTradeId(id);
                    operation.setUserId(0);
                    operation.setType(6);
                    operation.setCreatedTime(new Date());
                    secondTradeOperationMapper.insert(operation);
                }
            }
        } catch (Exception e) {
            log.error("SecondGoodsTradeXxlJob.secondTradeTimeoutFail Error Mgs={}", e.getMessage());
        }
    }

    /**
     * 二手交易平台 - 每分钟从redis中读取已读的消息id 并将数据库设为已读
     */
    @Scheduled(cron = "0 * * * * ?")
    public void readMessage() {
        if (!isEnable) {
            return;
        }

        log.info("开始执行定时任务: 二手交易平台 - 每分钟从redis中读取已读的消息id 并将数据库设为已读 - readMessage");
        try {
            if (CollectionUtil.isEmpty(baseRedisService.getList("readMessageIdKey"))) return;

            List<String> dataList = baseRedisService.popBatchFromList("readMessageIdKey");
            if (CollectionUtil.isNotEmpty(dataList)) {
                LambdaUpdateWrapper<LifeMessage> wrapper = new LambdaUpdateWrapper<>();
                wrapper.in(LifeMessage::getId, dataList)
                        .set(LifeMessage::getIsRead, 1);
                lifeMessageMapper.update(null, wrapper);
            }
        } catch (Exception e) {
            log.error("ScheduledTask.readMessage Error Mgs={}", e.getMessage());
        }
    }
}
