package com.zanxiang.game.module.manage.service.impl;

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.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zanxiang.erp.security.util.SecurityUtil;
import com.zanxiang.game.module.manage.enums.KfRoomMsgOwnerEnum;
import com.zanxiang.game.module.manage.enums.KfRoomMsgTypeEnum;
import com.zanxiang.game.module.manage.enums.OrderStateEnum;
import com.zanxiang.game.module.manage.pojo.dto.KfWebSocketMsgDTO;
import com.zanxiang.game.module.manage.pojo.params.KfWebSocketMsgParam;
import com.zanxiang.game.module.manage.service.*;
import com.zanxiang.game.module.mybatis.entity.*;
import com.zanxiang.game.module.mybatis.mapper.KfRoomMapper;
import com.zanxiang.module.util.JsonUtil;
import com.zanxiang.module.util.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : lingfeng
 * @time : 2024-02-23
 * @description : 客服聊天房间
 */
@Slf4j
@Service
public class KfRoomServiceImpl extends ServiceImpl<KfRoomMapper, KfRoom> implements IKfRoomService {

    @Autowired
    private IGameAuthService gameAuthService;

    @Autowired
    private IGameAppletService gameAppletService;

    @Autowired
    private IKfRoomMsgService kfRoomMsgService;

    @Autowired
    private IUserService userService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IRoleOperateService roleOperateService;

    @Autowired
    private IKfSessionUserService kfSessionUserService;

    @Autowired
    private IGameUserRoleService gameUserRoleService;

    @Override
    public Tuple2<KfWebSocketMsgDTO.PageBean, List<KfWebSocketMsgDTO.RoomBean>> getFinishRoomList(Long gameId, KfWebSocketMsgParam.PageBean pageBean) {
        Page<KfRoom> kfRoomPage = super.page(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()),
                new QueryWrapper<KfRoom>().lambda()
                        .eq(KfRoom::getGameId, gameId)
                        .eq(KfRoom::getOnline, Boolean.FALSE)
                        .orderByDesc(KfRoom::getUpdateTime)
        );
        List<KfWebSocketMsgDTO.RoomBean> roomBeanList = kfRoomPage.getRecords().stream()
                .map(this::transform).collect(Collectors.toList());
        return Tuples.of(KfWebSocketMsgDTO.transformPage(kfRoomPage), roomBeanList);
    }

    @Override
    public Long userJoinRoom(String openId, Long gameId) {
        KfRoom kfRoom = super.getOne(new LambdaQueryWrapper<KfRoom>().eq(KfRoom::getOpenId, openId));
        if (kfRoom == null) {
            kfRoom = this.transform(openId, gameId);
            super.save(kfRoom);
            return kfRoom.getId();
        }
        super.update(new LambdaUpdateWrapper<KfRoom>()
                .set(KfRoom::getKfUserId, SecurityUtil.getUserId())
                .set(KfRoom::getOnline, Boolean.TRUE)
                .set(KfRoom::getUpdateTime, LocalDateTime.now())
                .eq(KfRoom::getId, kfRoom.getId())
        );
        return kfRoom.getId();
    }

    private KfRoom transform(String openId, Long gameId) {
        User user = userService.getOne(new LambdaQueryWrapper<User>()
                .eq(User::getGameId, gameId)
                .eq(User::getOpenId, openId));
        return KfRoom.builder()
                .gameId(gameId)
                .openId(openId)
                .userId(user == null ? null : user.getId())
                .kfUserId(SecurityUtil.getUserId())
                .online(Boolean.TRUE)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();
    }

    @Override
    public List<KfWebSocketMsgDTO.GameBean> getKfGameList() {
        Long kfUserId = SecurityUtil.getUserId();
        List<GameAuth> gameAuthList = gameAuthService.list(new LambdaQueryWrapper<GameAuth>()
                .eq(!SecurityUtil.isAdmin(), GameAuth::getUserId, kfUserId));
        if (!SecurityUtil.isAdmin() && CollectionUtils.isEmpty(gameAuthList)) {
            return Collections.emptyList();
        }
        return gameAppletService.list(new LambdaQueryWrapper<GameApplet>()
                .in(!SecurityUtil.isAdmin(), GameApplet::getGameId,
                        gameAuthList.stream().map(GameAuth::getGameId).collect(Collectors.toSet()))
                .eq(GameApplet::getKfNew, Boolean.TRUE)
        ).stream().map(gameApplet -> this.transform(gameApplet, kfUserId)).collect(Collectors.toList());
    }

    @Override
    public List<KfWebSocketMsgDTO.GameBean> getKfGameByGameId(Long gameId, Long kfUserId) {
        GameApplet gameApplet = gameAppletService.getOne(new LambdaQueryWrapper<GameApplet>()
                .eq(GameApplet::getGameId, gameId));
        if (gameApplet == null) {
            return Collections.emptyList();
        }
        return Collections.singletonList(this.transform(gameApplet, kfUserId));
    }

    private KfWebSocketMsgDTO.GameBean transform(GameApplet gameApplet, Long kfUserId) {
        if (gameApplet == null) {
            return null;
        }
        long unReadMsgCount = kfRoomMsgService.count(new LambdaQueryWrapper<KfRoomMsg>()
                .eq(KfRoomMsg::getGameId, gameApplet.getGameId())
                .eq(KfRoomMsg::getReadStatus, Boolean.FALSE)
                .and(qw -> qw.eq(KfRoomMsg::getKfUserId, kfUserId)
                        .or().isNull(KfRoomMsg::getRoomId)
                )
                .eq(KfRoomMsg::getMsgOwner, KfRoomMsgOwnerEnum.KF_MSG_OWNER_USER.getValue()));
        KfWebSocketMsgDTO.GameBean gameBean = BeanUtil.copy(gameApplet, KfWebSocketMsgDTO.GameBean.class);
        gameBean.setUnReadMsgCount(unReadMsgCount);
        return gameBean;
    }

    @Override
    public List<KfWebSocketMsgDTO.RoomBean> getOnlineRoomList(Long gameId) {
        return super.list(new LambdaQueryWrapper<KfRoom>()
                .eq(KfRoom::getKfUserId, SecurityUtil.getUserId())
                .eq(KfRoom::getGameId, gameId)
                .eq(KfRoom::getOnline, Boolean.TRUE)
        ).stream().map(this::transform).collect(Collectors.toList());
    }

    @Override
    public List<KfWebSocketMsgDTO.RoomBean> getRoomByRoomId(Long roomId) {
        KfRoom kfRoom = super.getById(roomId);
        if (kfRoom == null) {
            return Collections.emptyList();
        }
        return Collections.singletonList(this.transform(kfRoom));
    }

    private KfWebSocketMsgDTO.RoomBean transform(KfRoom kfRoom) {
        if (kfRoom == null) {
            return null;
        }
        KfWebSocketMsgDTO.RoomBean roomBean = BeanUtil.copy(kfRoom, KfWebSocketMsgDTO.RoomBean.class);
        roomBean.setRoomId(kfRoom.getId());
        //最近角色信息
        KfSessionUser kfSessionUser = kfSessionUserService.getById(kfRoom.getOpenId(), kfRoom.getGameId());
        if (kfSessionUser != null) {
            roomBean.setLastRoleId(kfSessionUser.getLastRoleId());
            roomBean.setLastRoleName(kfSessionUser.getLastRoleName());
        }
        //未读消息数量
        long unReadMsgCount = kfRoomMsgService.count(new LambdaQueryWrapper<KfRoomMsg>()
                .eq(KfRoomMsg::getRoomId, kfRoom.getId())
                .eq(KfRoomMsg::getReadStatus, Boolean.FALSE)
                .eq(KfRoomMsg::getMsgOwner, KfRoomMsgOwnerEnum.KF_MSG_OWNER_USER.getValue()));
        roomBean.setUnReadMsgCount(unReadMsgCount);
        //最后一条消息
        KfRoomMsg kfRoomMsg = kfRoomMsgService.getOne(new LambdaQueryWrapper<KfRoomMsg>()
                .eq(KfRoomMsg::getRoomId, kfRoom.getId())
                .orderByDesc(KfRoomMsg::getSortTime)
                .last("limit 1"));
        if (kfRoomMsg != null) {
            if (Objects.equals(kfRoomMsg.getMsgType(), KfRoomMsgTypeEnum.KF_MSG_TYPE_TEXT.getValue())) {
                KfWebSocketMsgDTO.MsgContentBean msgContent = JsonUtil.toObj(kfRoomMsg.getContent(), KfWebSocketMsgDTO.MsgContentBean.class);
                roomBean.setLastMsg(msgContent.getText());
            }
            if (Objects.equals(kfRoomMsg.getMsgType(), KfRoomMsgTypeEnum.KF_MSG_TYPE_IMAGE.getValue())) {
                roomBean.setLastMsg("[图片]");
            }
            if (Objects.equals(kfRoomMsg.getMsgType(), KfRoomMsgTypeEnum.KF_MSG_TYPE_LINK.getValue())) {
                roomBean.setLastMsg("[充值]");
            }
            if (Objects.equals(kfRoomMsg.getMsgType(), KfRoomMsgTypeEnum.KF_MSG_TYPE_MINI_APP.getValue())) {
                roomBean.setLastMsg("[小程序]");
            }
            roomBean.setLastMsgTime(kfRoomMsg.getCreateTime());
            roomBean.setMsgOwner(kfRoomMsg.getMsgOwner());
        }
        //玩家是否加企微
        roomBean.setAddCorpWechat(roleOperateService.userAddCorpWechat(kfRoom.getGameId(), kfRoom.getUserId()));
        return roomBean;
    }

    @Override
    public KfWebSocketMsgDTO.UserBean getUserBean(String openId, Long gameId) {
        KfSessionUser kfSessionUser = kfSessionUserService.getById(openId, gameId);
        KfWebSocketMsgDTO.UserBean userBean = BeanUtil.copy(kfSessionUser, KfWebSocketMsgDTO.UserBean.class);
        if (userBean == null || userBean.getUserId() == null) {
            return userBean;
        }
        //查询订单
        List<Order> orderList = orderService.list(new LambdaQueryWrapper<Order>()
                .select(Order::getOrderId, Order::getAmount, Order::getPayTime)
                .eq(Order::getUserId, userBean.getUserId())
                .eq(kfSessionUser.getGameId() != null, Order::getGameId, kfSessionUser.getGameId())
                .eq(Order::getStatus, OrderStateEnum.SUCCESS_PAY.getCode()));
        //设置参数
        if (CollectionUtils.isNotEmpty(orderList)) {
            //订单数
            userBean.setOrderCount(orderList.size());
            //最大订单金额
            Optional<Order> maxAmountOrder = orderList.stream()
                    .max(Comparator.comparing(Order::getAmount));
            userBean.setOrderMaxAmount(maxAmountOrder.map(Order::getAmount).orElse(null));
            //最近支付时间
            Optional<Order> lastPayTimeOrder = orderList.stream()
                    .max(Comparator.comparing(Order::getPayTime));
            userBean.setLastPayTime(lastPayTimeOrder.map(Order::getPayTime).orElse(null));
            //支付总金额
            BigDecimal totalAmount = orderList.stream()
                    .map(Order::getAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            userBean.setOrderAmountSum(totalAmount);
        }
        //玩家是否加企微
        userBean.setAddCorpWechat(roleOperateService.userAddCorpWechat(kfSessionUser.getGameId(), kfSessionUser.getUserId()));
        return userBean;
    }

    @Override
    public Tuple2<KfWebSocketMsgDTO.PageBean, List<KfWebSocketMsgDTO.GameRoleBean>> getRoleBeanList(String openId, Long gameId, KfWebSocketMsgParam.PageBean pageBean) {
        KfSessionUser kfSessionUser = kfSessionUserService.getById(openId, gameId);
        if (kfSessionUser == null || kfSessionUser.getUserId() == null) {
            return Tuples.of(KfWebSocketMsgDTO.defaultPage(pageBean.getPageNum(), pageBean.getPageSize()), Collections.emptyList());
        }
        Page<GameUserRole> gameUserRolePage = gameUserRoleService.page(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()),
                new QueryWrapper<GameUserRole>().lambda()
                        .eq(GameUserRole::getUserId, kfSessionUser.getUserId())
                        .orderByDesc(GameUserRole::getCreateTime)
        );
        //构造角色列表
        List<KfWebSocketMsgDTO.GameRoleBean> gameRoleList = gameUserRolePage.getRecords().stream()
                .map(this::transform).collect(Collectors.toList());
        return Tuples.of(KfWebSocketMsgDTO.transformPage(gameUserRolePage), gameRoleList);
    }

    private KfWebSocketMsgDTO.GameRoleBean transform(GameUserRole gameUserRole) {
        if (gameUserRole == null) {
            return null;
        }
        return BeanUtil.copy(gameUserRole, KfWebSocketMsgDTO.GameRoleBean.class);
    }

    @Override
    public Tuple2<KfWebSocketMsgDTO.PageBean, List<KfWebSocketMsgDTO.OrderBean>> getOrderBeanList(String openId, Long gameId, KfWebSocketMsgParam.PageBean pageBean) {
        KfSessionUser kfSessionUser = kfSessionUserService.getById(openId, gameId);
        if (kfSessionUser == null || kfSessionUser.getUserId() == null) {
            return Tuples.of(KfWebSocketMsgDTO.defaultPage(pageBean.getPageNum(), pageBean.getPageSize()), Collections.emptyList());
        }
        Page<Order> orderPage = orderService.page(new Page<>(pageBean.getPageNum(), pageBean.getPageSize()),
                new QueryWrapper<Order>().lambda()
                        .eq(Order::getUserId, kfSessionUser.getUserId())
                        .eq(Order::getStatus, OrderStateEnum.SUCCESS_PAY.getCode())
                        .orderByDesc(Order::getCreateTime)
        );
        //构造订单列表
        List<KfWebSocketMsgDTO.OrderBean> orderList = orderPage.getRecords().stream()
                .map(this::transform).collect(Collectors.toList());
        return Tuples.of(KfWebSocketMsgDTO.transformPage(orderPage), orderList);
    }

    private KfWebSocketMsgDTO.OrderBean transform(Order order) {
        if (order == null) {
            return null;
        }
        return BeanUtil.copy(order, KfWebSocketMsgDTO.OrderBean.class);
    }

}
