package de.oaa.xxx.user;

import java.io.IOException;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Base64;
import java.util.Date;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.inject.Inject;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Consumes;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import jakarta.ws.rs.core.Response.Status;
import jakarta.ws.rs.core.UriInfo;

@ApplicationScoped
@Path("login")
public class LoginService {
	
	private String keyPass = "XUR!Rv&f$j3UsqD&";
	private String alias = "xxx";
	private Logger LOGGER = LoggerFactory.getLogger(getClass());

	@Inject private UserDAO dao;
	
	@GET
	@Produces(MediaType.TEXT_PLAIN)
	public Response login(@QueryParam("email") String email, @QueryParam("hash") String hash, @Context HttpServletRequest req) throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, UnrecoverableKeyException {
		UserEntity user = dao.login(email, hash);
		if (user != null) {
			LOGGER.info("User erolgreich angemeldet: " + email);
			KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
			keystore.load(getClass().getClassLoader().getResourceAsStream("/xxx.jks"), keyPass.toCharArray());
			Key key = keystore.getKey(alias, keyPass.toCharArray());
			JwtBuilder builder = Jwts.builder()
				.setIssuer("OAA Games")
				.setIssuedAt(new Date())
				.claim("email", email)
				.claim("client", req.getRemoteAddr())
				.claim("userId", user.getUserId())
				.signWith(key, SignatureAlgorithm.RS256);
			String token = builder.compact();
			if (LOGGER.isDebugEnabled()) {
				LOGGER.debug("Erstellter token: {}", token);
			}
			return Response.ok(token).build();
		} else {
			return Response.noContent().build();
		}
	}
	
	@POST
	@Consumes(MediaType.APPLICATION_JSON)
	public Response checkToken(@QueryParam("token") String token, @Context HttpServletRequest req, @Context UriInfo urlInfo) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException {
		KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
		keystore.load(getClass().getClassLoader().getResourceAsStream("/xxx.jks"), keyPass.toCharArray());
		Key key = keystore.getKey(alias, keyPass.toCharArray());
		
		Jws<Claims> claimsJws = Jwts.parserBuilder().setSigningKey(key).build().parseClaimsJws(token);
		String client = claimsJws.getBody().get("client").toString();
		UUID fromString = UUID.fromString(claimsJws.getBody().get("userId").toString());
		UserEntity user = dao.findById(fromString);
		if (user != null && user.getEmail().equals(claimsJws.getBody().get("email").toString()) && req.getRemoteAddr().equals(client)) {
			return Response.created(urlInfo.getAbsolutePathBuilder().path(user.getUserId().toString()).build()).build();
		} else {
			return Response.status(Status.BAD_REQUEST).build();
		}
	}
	
	@GET
	@Path("{userId}")
	@Produces(MediaType.APPLICATION_JSON)
	public Response get(@PathParam("userId") String userId) {
		UserEntity entity = dao.findById(UUID.fromString(userId));
		if (entity != null) {
			return Response.ok(entity.toUser()).build();
		} else {
			return Response.noContent().build();
		}
	}
	
	@GET
	@Path("publickey")
	@Produces(MediaType.TEXT_PLAIN)
	public Response getPK() throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
		KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
		keystore.load(getClass().getClassLoader().getResourceAsStream("/xxx.jks"), keyPass.toCharArray());
		String string = Base64.getEncoder().encodeToString(keystore.getCertificate(alias).getPublicKey().getEncoded());
		return Response.ok(string).build();
	}
}
