package code;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.NoSuchAlgorithmException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Base64;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;

import db.DBC;
import db.Dominio;
import io.fusionauth.jwt.InvalidJWTSignatureException;
import io.fusionauth.jwt.Verifier;
import io.fusionauth.jwt.domain.Algorithm;
import io.fusionauth.jwt.domain.JWT;
import io.fusionauth.jwt.rsa.RSAVerifier;

public class TokenHandler implements HttpHandler {

	public void handle(HttpExchange he) throws IOException {
		// URI requestedUri = he.getRequestURI();
		String requestMethod = he.getRequestMethod();

		if (requestMethod.compareToIgnoreCase("options") == 0) {
			Helper.sendCors(he, 200);
			return;
		}
		if (requestMethod.compareToIgnoreCase("GET") != 0) {
			// send Method not allowed
			// exchange.getResponseHeaders().remove("content-type");
			// String response = "{\"message\":\"Method not allowed!\"}";
			// Helper.sendCors(he,405,response);
			Helper.sendCors(he, 405);
			return;
		}

		// String query = requestedUri.getRawQuery();
		// String body = readBody(he.getRequestBody());
		String user;

		// String user = he.getRequestHeaders().get("user").get(0);

		// questo e' strano: headers dice { {} } mentre headers.get("Authorization")
		// riporta il token correttamente
		// System.out.println("Headers: "+he.getRequestHeaders());
		// System.out.println("Auth: "+he.getRequestHeaders().get("Authorization"));

		// System.out.println("token: " + token);

		if ((user = Helper.checkTokenGetUser(he)) == null) {
			Helper.sendCors(he, 401);
			return;
		}

		// System.out.println(body);

		// JSONObject chiave = new JSONObject();
		// chiamo http://localhost:8080/auth/realms/test00/protocol/openid-connect/certs
		// //probabilmente https

		// TOKEN____________________________________________________________________

		// {
		// "access_token":
		// "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJXZ2FCRjhidS05dVhhR0pNRzIxQWQtQTV3aW0xZ29oRnhNNXVvNTJrLWhJIn0.eyJleHAiOjE2NjIwMjQwMjgsImlhdCI6MTY2MjAyMzcyOCwiYXV0aF90aW1lIjoxNjYyMDIzNjYyLCJqdGkiOiIzMmUwODFmMi00MmZhLTQ2ZDEtOTliNy05OWY0MTRlNmM4MTciLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QwMCIsImF1ZCI6ImFjY291bnQiLCJzdWIiOiI2MGE4MjdjMS0zZDM3LTQ4ODEtYjU3Ny0zODNlZDUxNjE3MjgiLCJ0eXAiOiJCZWFyZXIiLCJhenAiOiJteWNsaWVudCIsIm5vbmNlIjoiYTgxZTFhODQtODg4NS00NzAyLWI4ZDEtZjZjNWEwZDFmYzRkIiwic2Vzc2lvbl9zdGF0ZSI6IjUyOTQwYWYzLTM0MjctNDVkZC04YWNhLWE0ZDYxMjdhNDQxZCIsImFjciI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOlsiaHR0cDovL2xvY2FsaG9zdDozMDAwIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJvZmZsaW5lX2FjY2VzcyIsImRlZmF1bHQtcm9sZXMtdGVzdDAwIiwidW1hX2F1dGhvcml6YXRpb24iXX0sInJlc291cmNlX2FjY2VzcyI6eyJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6Im9wZW5pZCBwcm9maWxlIGVtYWlsIiwic2lkIjoiNTI5NDBhZjMtMzQyNy00NWRkLThhY2EtYTRkNjEyN2E0NDFkIiwiZW1haWxfdmVyaWZpZWQiOmZhbHNlLCJuYW1lIjoiTWFyaW8gUm9zc2kiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJqb2huIiwiZ2l2ZW5fbmFtZSI6Ik1hcmlvIiwiZmFtaWx5X25hbWUiOiJSb3NzaSIsImVtYWlsIjoibWFyaW9AZ21haWwuY29tIn0.JQEmBY9zqVBelNorT3ZNyjXk6Bh0QbR1UO_1MTquS39njq8Fvd1h5ygan_v-YtlcTD9gz38O1OLhZEnK6QoUlUNfBybPrgM8GxcqTnmwYe2I5bJQ_7U6lqdWjgPJTBpLmy7faTj6_i2t0jVNKfTxJgzzbsTiYhJZZp-jvu05ZyMaQ3Q_wUYazb6VvbAkz9F2-8Uk04SxHVUsHjcinoyYd6jQP5TML3cVvwNk_eX2LavQk9o3XCQeBxsq9tUw7HsnSjtvPnuqHMe7S_Yg7_xp6QLVXdQAkOebFcvAMv8hMUMhXk0RV-RryhvQ85gF5NHgdvFhB6FPoXCO-T-SZpi6Qw",
		// "expires_in": 300,
		// "refresh_expires_in": 1800,
		// "refresh_token":
		// "eyJhbGciOiJIUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJkZDIyM2U5NC1mMjUxLTQ4MDAtYTI3Zi1jYzQzZjZhZTQzODEifQ.eyJleHAiOjE2NjIwMjU1MjgsImlhdCI6MTY2MjAyMzcyOCwianRpIjoiOTEwNWViMGUtMGJmMS00ODRlLTk1M2UtOGRmMTRkMzkwMGI4IiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MDgwL3JlYWxtcy90ZXN0MDAiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QwMCIsInN1YiI6IjYwYTgyN2MxLTNkMzctNDg4MS1iNTc3LTM4M2VkNTE2MTcyOCIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJteWNsaWVudCIsIm5vbmNlIjoiYTgxZTFhODQtODg4NS00NzAyLWI4ZDEtZjZjNWEwZDFmYzRkIiwic2Vzc2lvbl9zdGF0ZSI6IjUyOTQwYWYzLTM0MjctNDVkZC04YWNhLWE0ZDYxMjdhNDQxZCIsInNjb3BlIjoib3BlbmlkIHByb2ZpbGUgZW1haWwiLCJzaWQiOiI1Mjk0MGFmMy0zNDI3LTQ1ZGQtOGFjYS1hNGQ2MTI3YTQ0MWQifQ.ZqcOLMUwHPxQY2I0V9bPIy6TBTeUIcHEbxgnxhJrac0",
		// "token_type": "Bearer",
		// "id_token":
		// "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJXZ2FCRjhidS05dVhhR0pNRzIxQWQtQTV3aW0xZ29oRnhNNXVvNTJrLWhJIn0.eyJleHAiOjE2NjIwMjQwMjgsImlhdCI6MTY2MjAyMzcyOCwiYXV0aF90aW1lIjoxNjYyMDIzNjYyLCJqdGkiOiI5ZDEyYzUyZi1kZTdlLTQ4ZDctOTEzOC01Yjc5NGRjZjJmZDQiLCJpc3MiOiJodHRwOi8vbG9jYWxob3N0OjgwODAvcmVhbG1zL3Rlc3QwMCIsImF1ZCI6Im15Y2xpZW50Iiwic3ViIjoiNjBhODI3YzEtM2QzNy00ODgxLWI1NzctMzgzZWQ1MTYxNzI4IiwidHlwIjoiSUQiLCJhenAiOiJteWNsaWVudCIsIm5vbmNlIjoiYTgxZTFhODQtODg4NS00NzAyLWI4ZDEtZjZjNWEwZDFmYzRkIiwic2Vzc2lvbl9zdGF0ZSI6IjUyOTQwYWYzLTM0MjctNDVkZC04YWNhLWE0ZDYxMjdhNDQxZCIsImF0X2hhc2giOiJ5MGVaZGowZmZsbFBMN3U3SkxiSzFnIiwiYWNyIjoiMSIsInNpZCI6IjUyOTQwYWYzLTM0MjctNDVkZC04YWNhLWE0ZDYxMjdhNDQxZCIsImVtYWlsX3ZlcmlmaWVkIjpmYWxzZSwibmFtZSI6Ik1hcmlvIFJvc3NpIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiam9obiIsImdpdmVuX25hbWUiOiJNYXJpbyIsImZhbWlseV9uYW1lIjoiUm9zc2kiLCJlbWFpbCI6Im1hcmlvQGdtYWlsLmNvbSJ9.SjyYBuj4bz7ugyqJibNubaUmwUvuyiocPXrr745PQ8f-AzhI_ITxjG3m7_i9lRw_UpcPQrlSwZTPxhDFUS2eK8YGG4Qg_MEELO6Pvez25x1aLrfDRw2qiT8Eu5t-6fa_N7ztQtWuyw9ThMxmpBdGx3PBDimjIY7m9CHrgSEymJf2LJsC2CF68WvczDEoVVzoUikwmvFbVS1LWCCAOd7b3s07fqP61kyj_XFtcyZv29EIOlUsodPKdQhNiplBNU1st-l0pLRocGEvIjRngSQDzTW4aHAL-jQENW2od0N23IXKtTrPCx33gElfeuA9hvyb6c4d8CNFrw6AHKH0YsoGqQ",
		// "not-before-policy": 0,
		// "session_state": "52940af3-3427-45dd-8aca-a4d6127a441d",
		// "scope": "openid profile email"
		// }

		// CHIAVE
		// PUBBLICA________________________________________________________________
		// {
		// "keys": [
		// {
		// "kid": "WgaBF8bu-9uXaGJMG21Ad-A5wim1gohFxM5uo52k-hI",
		// "kty": "RSA",
		// "alg": "RS256",
		// "use": "sig",
		// "n":
		// "qoJMLXqIHoBKq5vE7EYVdvxpwqOjPkeTUSb1rdhJs8ZpfCOQk7PYlNu-ykl4PAjYS5sVs5gQSzEwtTZ3vz1y8Ry0V1Xa3c3wk77NzahMO9QnAXa0cqFWhaIr4l0oKhRy-57hNIthkiRuDDlWBREb5sqk8OWxarznEVRykaC4178ccQrv6T3T5VGzxV1lCcBDzQchx_c9_v-tcQVGeyBhdm9uFARbxGG-91kDxSv3MKQbjdwp9csr2QDwuFgcBSB4Ul-9oMCZiVDpgWuoCy_ZxsI22WYAPT8KyaYts-0v7B89hPPweR7TzbmQHEGMfl0U_qEBdQw0N9P2KRapol7RyQ",
		// "e": "AQAB",
		// "x5c": [
		// "MIICmzCCAYMCBgGCkqLMcTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZ0ZXN0MDAwHhcNMjIwODEyMTUxNjU4WhcNMzIwODEyMTUxODM4WjARMQ8wDQYDVQQDDAZ0ZXN0MDAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqgkwteogegEqrm8TsRhV2/GnCo6M+R5NRJvWt2Emzxml8I5CTs9iU277KSXg8CNhLmxWzmBBLMTC1Nne/PXLxHLRXVdrdzfCTvs3NqEw71CcBdrRyoVaFoiviXSgqFHL7nuE0i2GSJG4MOVYFERvmyqTw5bFqvOcRVHKRoLjXvxxxCu/pPdPlUbPFXWUJwEPNByHH9z3+/61xBUZ7IGF2b24UBFvEYb73WQPFK/cwpBuN3Cn1yyvZAPC4WBwFIHhSX72gwJmJUOmBa6gLL9nGwjbZZgA9PwrJpi2z7S/sHz2E8/B5HtPNuZAcQYx+XRT+oQF1DDQ30/YpFqmiXtHJAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAHF8qo6bVlpt/44OxqnSFDY0wIxcunFIbA05ggox/5oAQvdoTD1LB8sfuLa3dtA/ysnnZDytk+vr8V4feYdSvAbtCWVq3yJgt7Dhe7ueP45v4WPJPcPqv8kMYtbkh0mivF2mYVLsEbZK46kBXN4Gkpv1oRDl2b04rfO7abv0dqb3eFs5QiJtKd1az1ckrTYFHdcB5TiiMaPq8/ikmInYKMvRW5H+NmjRvQf6dhKaSj1+cgcZ5xwVlOuubUyJHABKcK6dfnznwA/Ri3fzYXnG5p7mDazdeOQlNRHMK5SM2D6QRunmufg8ulmM+vhxg5ri8o1WqIkA03z+w44vQFy28Xo="
		// ],
		// "x5t": "ip8I56vsh3-VgNBfzigD3oiIwsg",
		// "x5t#S256": "1aZ1N3a_PeHLpZeLIbyfyqUjUKJ9NYWMP7-9H2arYWM"
		// },
		// {
		// "kid": "-0j9GoUrm6Fjs8sxcwaNe9R9mqr7bmgSRQ_nRp72iIs",
		// "kty": "RSA",
		// "alg": "RSA-OAEP",
		// "use": "enc",
		// "n":
		// "kpxC6pFuQnQVq8KoO3uMaFrfKC00jBbHfkx8HYuCIblQGap3xjcLGfMbd2EP2Hz2c38dmWcCMS6GgxUU10rlnWc4HKZ5jYCVTEdjU4nkmArzVipG03HzVb-3Eftz1hb4z8Qyjw616tjwQtaQRCvtx9o_UhmxG6YIeJhauN_Zh9z6ZHJ8bY6N242vk_ryJmaTsQ-GyOmU5h16mMrGCjMJ_uMiy38dITySNFGKwnJHaKU8H6V25UuGVgNl-Wjpk5L2bAdSkDEblJ7SsvzoYLGYzCUeCHhztWbNOy_sc31awULdTWEgH8SKvOWf3qZY1siItHBqHLHlHo5lNIMzhowGrw",
		// "e": "AQAB",
		// "x5c": [
		// "MIICmzCCAYMCBgGCkqLNYTANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDDAZ0ZXN0MDAwHhcNMjIwODEyMTUxNjU5WhcNMzIwODEyMTUxODM5WjARMQ8wDQYDVQQDDAZ0ZXN0MDAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCSnELqkW5CdBWrwqg7e4xoWt8oLTSMFsd+THwdi4IhuVAZqnfGNwsZ8xt3YQ/YfPZzfx2ZZwIxLoaDFRTXSuWdZzgcpnmNgJVMR2NTieSYCvNWKkbTcfNVv7cR+3PWFvjPxDKPDrXq2PBC1pBEK+3H2j9SGbEbpgh4mFq439mH3Ppkcnxtjo3bja+T+vImZpOxD4bI6ZTmHXqYysYKMwn+4yLLfx0hPJI0UYrCckdopTwfpXblS4ZWA2X5aOmTkvZsB1KQMRuUntKy/OhgsZjMJR4IeHO1Zs07L+xzfVrBQt1NYSAfxIq85Z/epljWyIi0cGocseUejmU0gzOGjAavAgMBAAEwDQYJKoZIhvcNAQELBQADggEBAE9kzDnbCjywK6QXECR8citVNaqarf3QQYDzSNakWgrGTTjdStASwEsPJvYJJ5Q6tl6ndqv4gflKq8STrmlHd4Ly+QHnXDwzrzjuSydZDAjYVcacMpZ4PAOAci0R6AmXTynIzyxU92LOlOWiF3ChG7uMRq7yLCNWo1jZxUepGo5z9LyIRGO4Pb878nhWL5PvXC95/vnbx2hSN7T6Uft3j3/94+fgIP4rmO2IWsDuc6fza/J07fK42Mtysy6FqBwhrimDMq+3OnTmdhSRL4pVVrRPSpYO/Czw9ra8hgGoAhu4G4FhTKAr8K75QaMdTtShpBMVNrImOq9kHtOoZJCJW0g="
		// ],
		// "x5t": "AU5GWMxLtE_hFDiJevWYEql-n4A",
		// "x5t#S256": "43Rx3Dsp6j_NLNwVx__Pb6mz07KrCa8xzH0pKOoV06g"
		// }
		// ]
		// }

		// The x5c filed value is copied between —–BEGIN CERTIFICATE—–
		//
		// —–END CERTIFICATE—– directives .

		// Build an EC verifier using an EC Public Key. A verifier may also be built
		// using the PublicKey object.
		// Verifier verifier = ECVerifier.newVerifier(Paths.get("public_key.pem"));
		//
		// // Verify and decode the encoded string JWT to a rich object
		// JWT jwt = JWT.getDecoder().decode(encodedJWT, verifier);
		//
		// // Assert the subject of the JWT is as expected
		// assertEquals(jwt.subject, "f1e33ab3-027f-47c5-bb07-8dd8ab37a2d3");
		// verifica token
		// if token !ok return

		// try {
		// verificaToken(token,signature);
		// } catch (NoSuchAlgorithmException | IOException | JSONException e1) {
		// e1.printStackTrace();
		// }

		// ricavo da token


		JSONObject res = new JSONObject();
		JSONArray rs = new JSONArray();

		ArrayList<String> domList;
		try {
			domList = DBC.getDomainsUser(user);

			for (String k : domList) {
				JSONObject ogg = new JSONObject();
				ogg.put("nome", k);

				Dominio d = DBC.getDomain(k);
				ogg.put("stato", d.getStatus());
				ogg.put("admin", false);

				rs.put(ogg);
			}
			domList.clear();
			domList = DBC.getDomainsAdmin(user);
			for (String k : domList) {
				JSONObject ogg = new JSONObject();
				ogg.put("nome", k);// domain

				Dominio d = DBC.getDomain(k);
				ogg.put("stato", d.getStatus());
				ogg.put("admin", true);

				rs.put(ogg);

			}

			res.put("response", rs);
		} catch (SQLException | JSONException e) {
			e.printStackTrace();
			return;
		}

		String response = res.toString();
		Helper.sendCors(he, 200, response);

		// JSONObject j=new JSONObject();
		// j.append("User", DBC.getDomainsUser(user));

		// j=(""+":"+);
	}

	public static String verificaToken(String encodedJWT, String signature)
			throws IOException, JSONException, NoSuchAlgorithmException {

		URL url = new URL(
				Helper.getKeycloakURL() + "realms/" + Helper.getKeycloakRealm() + "/protocol/openid-connect/certs");// maybe,
																													// se
																													// CloudAppe
																													// è
																													// localhost
																													// porta
																													// 8080
		HttpURLConnection con = (HttpURLConnection) url.openConnection();
		// 3000/install da inserire
		con.setRequestMethod("GET");
		con.setRequestProperty("Content-Type", "application/json");
		con.setRequestProperty("Accept", "application/json");
		con.setDoOutput(true);
		con.setConnectTimeout(5000);
		con.setReadTimeout(5000);

		// DataOutputStream out = new DataOutputStream(con.getOutputStream());//
		// inserimento param in call
		// out.writeBytes(j.toString());//
		// ParameterStringBuilder.getParamsString(parameters));
		// out.flush();
		// out.close();

		// con.setRequestProperty("Content-Type", "application/json");
		// String contentType = con.getHeaderField("Content-Type");

		// leggo risposta
		int status = con.getResponseCode();

		BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
		String inputLine;
		StringBuffer content = new StringBuffer();
		while ((inputLine = in.readLine()) != null) {
			content.append(inputLine);
		}
		in.close();
		con.disconnect();

		JSONObject j = new JSONObject(content.toString());
		JSONArray arr = j.getJSONArray("keys");
		JSONObject ogg = arr.getJSONObject(0);
		String chiave = ogg.getJSONArray("x5c").get(0).toString();
		String cert = "-----BEGIN CERTIFICATE-----\n" + chiave + "\n-----END CERTIFICATE-----";

		Verifier verifier = RSAVerifier.newVerifier(cert);
		try {
			int index = encodedJWT.lastIndexOf('.');
			byte[] message = encodedJWT.substring(0, index).getBytes(StandardCharsets.UTF_8);
			// message = token.header + token.body (tokSplit[0]+"."+tokSplit[1])
			byte[] signatureBytes = Base64.getUrlDecoder().decode(signature);// signature = tokSplit[2]
			verifier.verify(Algorithm.RS256, message, signatureBytes);
		} catch (InvalidJWTSignatureException e) {
			return null;
		}
		// Verify and decode the encoded string JWT to a rich object
		JWT jwt = JWT.getDecoder().decode(encodedJWT, verifier);
		/*
		 * {
		 * "aud" : "account",
		 * "exp" : 1662288513,
		 * "iat" : 1662288213,
		 * "iss" : "http://localhost:8080/realms/test00",
		 * "sub" : "60a827c1-3d37-4881-b577-383ed5161728",
		 * "jti" : "719379f0-0b22-40fd-ae35-0f523ffd9d4e",
		 * "auth_time" : 1662285948,
		 * "typ" : "Bearer",
		 * "azp" : "myclient",
		 * "nonce" : "a81e1a84-8885-4702-b8d1-f6c5a0d1fc4d",
		 * "session_state" : "969cdd2d-07db-4366-8180-d1ff15ddce20",
		 * "acr" : "0",
		 * "allowed-origins" : [ "http://localhost:3000" ],
		 * "realm_access" : {
		 * "roles" : [ "offline_access", "default-roles-test00", "uma_authorization" ]
		 * },
		 * "resource_access" : {
		 * "account" : {
		 * "roles" : [ "manage-account", "manage-account-links", "view-profile" ]
		 * }
		 * },
		 * "scope" : "openid profile email",
		 * "sid" : "969cdd2d-07db-4366-8180-d1ff15ddce20",
		 * "email_verified" : false,
		 * "name" : "Mario Rossi",
		 * "preferred_username" : "john",
		 * "given_name" : "Mario",
		 * "family_name" : "Rossi",
		 * "email" : "mario@gmail.com"
		 * }
		 */
		return jwt.getString("preferred_username");
	}

}