package enea.lecservice.security.controller;

import enea.lecservice.models.dto.ServiceResponse;
import enea.lecservice.security.IUserInfoService;
import enea.lecservice.security.InMemoryUserInfoService;
import enea.lecservice.security.dto.AuthRequest;
import enea.lecservice.security.dto.UserInfo;
import enea.lecservice.security.jwt.JWTUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtParser;
import io.jsonwebtoken.Jwts;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;

import java.util.LinkedHashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.stereotype.Controller;

@Log4j2
@Controller
@RequiredArgsConstructor
public class AbstractSecurityController {

    protected final AuthenticationManager authenticationManager;
    protected final InMemoryUserInfoService userDetailsService;
    protected final JWTUtil jwtUtil;
    protected final IUserInfoService userInfoService;

    @Value("${authentication.secret}")
    private String secretClient;
    
    public ResponseEntity<ServiceResponse> authenticate(AuthRequest request) throws Exception {
        authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
        final UserInfo userInfo = userDetailsService.loadUserByUsername(request.getUsername());

        String newToken;
        if (userInfo.getToken() != null)
            newToken = jwtUtil.generateToken(userInfo, userInfo.getToken().getCreation(), userInfo.getToken().getExpiration());
        else
            newToken = jwtUtil.generateToken(userInfo);

        return ResponseEntity.ok(ServiceResponse.Success(new Object () {
            public String token = newToken;
            public UserInfo user = userInfo;
        }));
    }

	public ResponseEntity<ServiceResponse> authenticateWithToken(String token) throws Exception {
		String remoteToken = "";
		String username = "";
		
		try {
		//	String secretClient2 = "hSmwAnRuBz52nIadhN8aEWVGHCXpjRNF";
			JwtParser p = Jwts.parser().setSigningKey(secretClient.getBytes());
			remoteToken = (String) p.parseClaimsJws(token).getBody().get("token");
			Map<String, String> user  = (Map<String, String>) p.parseClaimsJws(token).getBody().get("user");
			username = user.get("email");
		} catch (Exception e) {
			log.error("Secret Client key: " + secretClient);
			log.error("Received token: " + token);
			log.error(e.getLocalizedMessage());
		}
		authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(remoteToken, ""));
		
		final UserInfo userInfo = userDetailsService.loadUserByUsername(username);
		
		 String newToken;
	        if (userInfo.getToken() != null)
	            newToken = jwtUtil.generateToken(userInfo, userInfo.getToken().getCreation(), userInfo.getToken().getExpiration());
	        else
	            newToken = jwtUtil.generateToken(userInfo);
		
		return ResponseEntity.ok(ServiceResponse.Success(new Object () {
            public String token = newToken;
            public UserInfo user = userInfo;
        }));
		
		
	}
}
