package cn.wise.sc.energy.power.plant.business.security;

import cn.wise.sc.energy.power.plant.business.config.MyApplicationContextAware;
import cn.wise.sc.energy.power.plant.business.domain.UserInfo;
import cn.wise.sc.energy.power.plant.common.core.bean.BaseResponse;
import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationServiceException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.OffsetDateTime;
import java.util.Date;
import java.util.concurrent.TimeUnit;

import static cn.wise.sc.energy.power.plant.business.security.SecurityConstants.AUTHORIZATION_HEADER;
import static cn.wise.sc.energy.power.plant.business.security.SecurityConstants.TOKEN_PREFIX;


public class JWTAuthenticationFilter extends
        UsernamePasswordAuthenticationFilter {

    private final AuthenticationManager authenticationManager;
    private final ObjectMapper objectMapper = new ObjectMapper();


    public JWTAuthenticationFilter(
            final AuthenticationManager authenticationManager) {
        this.authenticationManager = authenticationManager;
    }

    @Override
    public Authentication attemptAuthentication(final HttpServletRequest request,
                                                final HttpServletResponse response) throws AuthenticationException {
        try {

            final LoginRequest loginRequest = this.objectMapper
                    .readValue(request.getInputStream(), LoginRequest.class);
            return this.authenticationManager.authenticate(
                    new UsernamePasswordAuthenticationToken(
                            loginRequest.getUsername(),
                            loginRequest.getPassword()));
        } catch (final IOException e) {
            throw new AuthenticationServiceException(e.getMessage(), e);
        }
    }

    RedissonClient redissonClient  = (RedissonClient) MyApplicationContextAware.getApplicationContext().getBean("redissonSingle");
    @Override
    protected void successfulAuthentication(final HttpServletRequest request,
                                            final HttpServletResponse response, final FilterChain chain,
                                            final Authentication authResult) {
        UserInfo info = (UserInfo) authResult.getPrincipal();
        final String token = Jwts.builder()
                .setSubject(info.getUsername())
                .setIssuedAt(new Date())
                .setExpiration(Date.from(OffsetDateTime.now().plusDays(5).toInstant()))
                .signWith(SignatureAlgorithm.HS256,JWTKeyHolder.RISEN_KEY)
                .compact();
        RBucket<String> cacheToken = redissonClient.getBucket("token:" + info.getUsername());
        cacheToken.set(token,24, TimeUnit.HOURS);
        response.addHeader(AUTHORIZATION_HEADER, TOKEN_PREFIX + token);
        try {
            String role = ((UserInfo) authResult.getPrincipal()).getRole() + "";
            String rts = JSON.toJSONString(BaseResponse.okData(role));
            response.setHeader("Content-type", "text/html;charset=UTF-8");
            response.setCharacterEncoding("utf-8");
            response.getWriter().write(rts);
        } catch (IOException e) {
            e.printStackTrace();
        }
//        response.addCookie(new Cookie(SecurityConstants.AUTH_COOKIE, token));
    }
}
