package com.ym.im.handler;

import com.ym.im.entity.MsgBody;
import com.ym.im.entity.base.BaseSocketInfo;
import com.ym.im.entity.base.ChannelAttributeKey;
import com.ym.im.entity.base.NettyConstant;
import com.ym.im.entity.enums.RoleEnum;
import com.ym.im.exception.HttpException;
import com.ym.im.factory.SingleChatFactory;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Optional;

import static io.netty.handler.codec.http.HttpResponseStatus.BAD_REQUEST;
import static io.netty.handler.codec.http.HttpResponseStatus.UNAUTHORIZED;
import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;


/**
 * @author: JJww
 * @Date:2020/10/10
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class WebSocketHandshakerHandler extends BaseHandler<FullHttpRequest> {

    @Autowired
    private ChannelGroupHandler channelGroup;

    @Autowired
    private SingleChatFactory singleChatFactory;

    public static final String ROLE_TYPE = "RoleType";

    public static final String MERCHANT_ID = "MerchantId";

    public static final String AUTHORIZATION = "Authorization";

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest fullHttpRequest) throws Exception {

        final String token = fullHttpRequest.headers().get(AUTHORIZATION);
        Optional.ofNullable(token).orElseThrow(() -> new HttpException(ctx, fullHttpRequest, new DefaultFullHttpResponse(HTTP_1_1, UNAUTHORIZED)));
        final String roleType = fullHttpRequest.headers().get(ROLE_TYPE, null);
        Optional.ofNullable(roleType).orElseThrow(() -> new HttpException(ctx, fullHttpRequest, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST)));
        if (RoleEnum.merchant.getType().equals(roleType)) {
            final Object merchantId = fullHttpRequest.headers().get(MERCHANT_ID);
            Optional.ofNullable(merchantId).orElseThrow(() -> new HttpException(ctx, fullHttpRequest, new DefaultFullHttpResponse(HTTP_1_1, BAD_REQUEST)));
            ctx.channel().attr(ChannelAttributeKey.MERCHANT_ID).set(Long.valueOf(merchantId.toString()));
        }
        final Long userId = Long.valueOf(fullHttpRequest.headers().get(MERCHANT_ID)); //待完善鉴权逻辑
        ctx.channel().attr(ChannelAttributeKey.ROLE_ID).set(userId);
        ctx.channel().attr(ChannelAttributeKey.TOKEN_INFO).set(token);
        ctx.channel().attr(ChannelAttributeKey.ROLE_TYPE).set(roleType);
        this.sso(token, userId, roleType);
        singleChatFactory.getService(roleType).init(ctx);
        fullHttpRequest.setUri(NettyConstant.CS);
        ctx.fireChannelRead(fullHttpRequest.retain());
    }


    private void sso(String token, Long roleId, String type) {
        BaseSocketInfo baseSocketInfo = null;
        switch (RoleEnum.get(type)) {
            case APP:
                baseSocketInfo = channelGroup.USER_GROUP.get(roleId);
                channelGroup.USER_GROUP.remove(roleId);
                break;
            case merchant:
                baseSocketInfo = channelGroup.getMerchantStaff(roleId);
                channelGroup.removeMerchantStaff(roleId);
                break;
            default:
        }
        if (baseSocketInfo != null && !token.equals(baseSocketInfo.getToken())) {
            baseSocketInfo.writeAndFlush(new MsgBody<>().setStatus(MsgBody.FORCEDOFFLINE));
            baseSocketInfo.close();
            log.info("用户: " + roleId + " 被迫下线");
        }
    }
}
