package com.sqx.common.websocket;


import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.sqx.modules.artificer.dao.ArtificerDao;
import com.sqx.modules.artificer.dao.UserRechargeDao;
import com.sqx.modules.artificer.entity.Artificer;
import com.sqx.modules.artificer.entity.UserRecharge;
import com.sqx.modules.common.dao.CommonInfoDao;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;

/**
 * @description:WebSocketServer 操作类
 * @author：zc.
 * @createData：2024-1-10 下午 4:21
 * @projectName：anmo
 * @className：WebSocketServer
 * @packageName：com.sqx.websocket
 */
@ServerEndpoint("/ws/{userId}")
@Component
@Slf4j
public class WebSocketServer {

    @Autowired
    private ArtificerDao artificerDao;
    @Autowired
    private UserRechargeDao userRechargeDao;
    @Autowired
    private CommonInfoDao commonInfoDao;
    //静态初始化
    public static WebSocketServer webSocketServer;

    //保证Bean初始化前已经装配了属性
    @PostConstruct
    public void init() {
        webSocketServer = this;
    }

    // 与某个客户端的连接会话，需要通过它来给客户端发送数据
    private String userId;


    // session集合,存放对应的session
    private static ConcurrentHashMap<String, Session> sessionPool = new ConcurrentHashMap<>();

    // concurrent包的线程安全Set,用来存放每个客户端对应的WebSocket对象。
    private static CopyOnWriteArraySet<WebSocketServer> webSocketSet = new CopyOnWriteArraySet<>();

    /**
     * 建立WebSocket连接
     *
     * @param session
     * @param userId  用户ID
     */
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") String userId) {
        log.info("WebSocket建立连接中,连接用户ID：{}", userId);
        try {
            Session historySession = sessionPool.get(userId);
            // historySession不为空,说明已经有人登陆账号,应该删除登陆的WebSocket对象
            if (historySession != null) {
                webSocketSet.remove(historySession);
                historySession.close();
            }
        } catch (IOException e) {
            log.error("重复登录异常,错误信息：" + e.getMessage(), e);
        }
        // 建立连接
        this.userId = userId;
        webSocketSet.add(this);
        sessionPool.put(userId, session);
        log.info("建立连接完成,当前在线人数为：{}", webSocketSet.size());
    }

    /**
     * 发生错误
     *
     * @param throwable e
     */
    @OnError
    public void onError(Throwable throwable) {
        throwable.printStackTrace();
    }

    /**
     * 连接关闭
     */
    @OnClose
    public void onClose() {
        turnOffTheGoLive(this.userId);
        webSocketSet.remove(this);
        sessionPool.remove(this.userId);
        log.info("连接断开,当前在线人数为：{}", webSocketSet.size());
    }


    /**
     * 技师在线强制退出应用，改为离线状态
     *
     * @param userId 技师id
     */
    public void turnOffTheGoLive(String userId) {
        Artificer artificer = webSocketServer.artificerDao.selectOne(Wrappers.<Artificer>lambdaUpdate().eq(Artificer::getUserId, userId));
        Artificer artificerUpd = new Artificer();
        artificerUpd.setStatus(2);
        artificerUpd.setArtificerId(artificer.getArtificerId());
        webSocketServer.artificerDao.updateById(artificerUpd);

        Integer i = Integer.valueOf(webSocketServer.commonInfoDao.findOne(100000).getValue());
        Date upTime = artificer.getUpTime();
        long betweenDay = DateUtil.between(upTime, new Date(), DateUnit.MINUTE);
        int i1 = new Long(betweenDay).intValue();
        int count = i1 / i;
        for (int i2 = 0; i2 < count; i2++) {
            UserRecharge userRecharge = new UserRecharge();
            userRecharge.setArtificerId(artificer.getArtificerId());
            userRecharge.setUserRecharge(new BigDecimal("1"));
            userRecharge.setType("1");
            upTime = DateUtil.offsetMinute(upTime, i);
            userRecharge.setCreateTime(upTime.toString());
            webSocketServer.userRechargeDao.insert(userRecharge);
        }

    }
}