package com.ruoyi.cai.chat;

import com.ruoyi.cai.domain.Account;
import com.ruoyi.cai.domain.Anchor;
import com.ruoyi.cai.domain.User;
import com.ruoyi.cai.domain.UserCall;
import com.ruoyi.cai.dto.app.dto.GuardNum;
import com.ruoyi.cai.dto.app.query.CallReq;
import com.ruoyi.cai.dto.app.vo.chat.CallResp;
import com.ruoyi.cai.dto.app.vo.chat.GetRoomResp;
import com.ruoyi.cai.enums.SystemConfigEnum;
import com.ruoyi.cai.manager.IdManager;
import com.ruoyi.cai.manager.SystemConfigManager;
import com.ruoyi.cai.service.*;
import com.ruoyi.cai.ws.bean.Room;
import com.ruoyi.cai.ws.constant.RedisConstant;
import com.ruoyi.cai.ws.dto.WsToken;
import com.ruoyi.cai.ws.manager.WebSocketManager;
import com.ruoyi.cai.ws.util.MapGetUtil;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.Duration;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Component
public class ChatManager {
    @Autowired
    private UserService userService;
    @Autowired
    private AnchorService anchorService;
    @Autowired
    private WebSocketManager webSocketManager;
    @Autowired
    private UserCallService userCallService;
    @Autowired
    private SystemConfigManager systemConfigManager;
    @Autowired
    private GuardTotalService guardTotalService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private AccountService accountService;

    private String setWsToken(Long roomId,Long fromUid,Long toUid,Long userId){
        String token = IdManager.nextIdStr();
        String tokenKey = String.format(RedisConstant.WS_TOKEN, token);
        Map<String,Object> map = new HashMap<>();
        map.put("roomId",roomId);
        map.put("fromUid",fromUid);
        map.put("toUid",toUid);
        map.put("userId",userId);
        RMap<Object, Object> mapRedis = redissonClient.getMap(tokenKey);
        mapRedis.putAll(map);
        mapRedis.expire(Duration.ofDays(1));
        return token;
    }

    public WsToken getToken(String token){
        String tokenKey = String.format(RedisConstant.WS_TOKEN, token);
        RMap<Object, Object> mapRedis = redissonClient.getMap(tokenKey);
        Map<Object, Object> entries = mapRedis.readAllMap();
        if(entries.isEmpty()){
            return null;
        }
        WsToken wsToken = new WsToken();
        wsToken.setRoomId(MapGetUtil.getLong(entries.get("roomId")));
        wsToken.setFromUid(MapGetUtil.getLong(entries.get("fromUid")));
        wsToken.setToUid(MapGetUtil.getLong(entries.get("toUid")));
        wsToken.setUserId(MapGetUtil.getLong(entries.get("userId")));
        return wsToken;
    }

    public CallResp call(CallReq callReq){
        Long userId = LoginHelper.getUserId();
        User fromUser = userService.getById(userId);
        User toUser = userService.getById(callReq.getToUid());
        if(toUser == null){
            throw new ServiceException("主播不存在");
        }
        if(toUser.getIsAnchor() != 1){
            throw new ServiceException("对方未通过女神认证，不能接听视频");
        }
        if(fromUser.getGender() == 1 && toUser.getGender() == 1){
            throw new ServiceException("主播和主播之间，不可以拨打视频哦~");
        }
        Anchor anchor = anchorService.getByUserId(toUser.getId());
        if(anchor == null){
            throw new ServiceException("主播技能不存在");
        }
        Account account = accountService.getByUserId(userId);
        if(account == null){
            throw new ServiceException("账户异常,请联系客服");
        }
        long coin = account.getIncomeCoin() + account.getCoin();
        if(coin < anchor.getPrice()*2){
            throw new ServiceException("您的余额不足，请充值");
        }
        Long roomId = null;
        Room room = webSocketManager.checkOnlineRoom(fromUser.getId(), toUser.getId());
        if(room == null){
            UserCall call = userCallService.createCall(fromUser, toUser, anchor);
            roomId = webSocketManager.createRoom(call.getId());
        }else{
            roomId = room.getRoomId();
        }
        String wsSocketUrlFormat = systemConfigManager.getWebSocketUrl();
        String token = setWsToken(roomId, fromUser.getId(), toUser.getId(),userId);
        String weSocketUrl = String.format(wsSocketUrlFormat,token,roomId);
        Long guardPrice = systemConfigManager.getSystemConfigOfLong(SystemConfigEnum.GUARD_PRICE);
        // 获取鉴黄规则 TODO
        CallResp callResp = new CallResp();
        callResp.setRoomId(roomId);
        callResp.setFromUid(fromUser.getId());
        callResp.setFromNickname(fromUser.getNickname());
        callResp.setFromAvatar(fromUser.getAvatar());
        callResp.setToUid(toUser.getId());
        callResp.setToNickname(toUser.getNickname());
        callResp.setToAvatar(toUser.getAvatar());
        callResp.setSocketUrl(weSocketUrl);
        callResp.setPrice(anchor.getPrice());
        callResp.setScore(anchor.getGiveScore());
        callResp.setServiceCount(anchor.getServiceCount());
        callResp.setServiceTime(anchor.getServiceTime());
        GuardNum guardNum = guardTotalService.getGuardNum(fromUser.getId(), toUser.getId());
        callResp.setGuardDiffNum(guardNum.getDiffNum());
        callResp.setGuardPrice(guardPrice);
        return callResp;
    }

    public GetRoomResp getRoom(String roomId){
        Long userId = LoginHelper.getUserId();
        UserCall userCall = userCallService.getById(roomId);
        if(userCall == null){
            throw new ServiceException("房间不存在");
        }
        if(!userCall.getFromUid().equals(userId) && !userCall.getToUid().equals(userId)){
            throw new ServiceException("无权限操作房间");
        }
        Room room = webSocketManager.checkOnlineRoom(userCall.getFromUid(), userCall.getToUid());
        if (room == null) {
            throw new ServiceException("'对方已取消通话'");
        }
        List<User> userList = userService.listByIds(Arrays.asList(userCall.getFromUid(), userCall.getToUid()));
        Map<Long, User> userMap = userList.stream().collect(Collectors.toMap(User::getId, Function.identity()));
        User fromUser = userMap.get(userCall.getFromUid());
        User toUser = userMap.get(userCall.getToUid());
        Anchor anchor = anchorService.getByUserId(toUser.getId());
        String wsSocketUrlFormat = systemConfigManager.getWebSocketUrl();
        String token = setWsToken(userCall.getId(), fromUser.getId(), toUser.getId(), userId);
        String weSocketUrl = String.format(wsSocketUrlFormat,token,roomId);
        GetRoomResp getRoomResp = new GetRoomResp();
        getRoomResp.setRoomId(userCall.getId()+"");
        getRoomResp.setFromUid(userCall.getFromUid());
        getRoomResp.setFromNickname(fromUser.getNickname());
        getRoomResp.setFromAvatar(fromUser.getAvatar());
        getRoomResp.setToUid(userCall.getToUid());
        getRoomResp.setToNickname(toUser.getNickname());
        getRoomResp.setToAvatar(toUser.getAvatar());
        getRoomResp.setSocketUrl(weSocketUrl);
        getRoomResp.setPrice(anchor.getPrice());
        getRoomResp.setScore(anchor.getGiveScore());
        getRoomResp.setServiceCount(anchor.getServiceCount());
        getRoomResp.setServiceTime(anchor.getServiceTime());
        return getRoomResp;
    }

}
