package demo.examples.rest;

import java.io.IOException;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

import java.util.HashMap;
import java.util.Map;

import com.sun.net.httpserver.HttpExchange;

import demo.config.Secrets;
import demo.server.Server;
import es.redsys.lib.GenerateRedirectForm;
import es.redsys.lib.Merchant;
import es.redsys.lib.Parameters;
import es.redsys.lib.Response;
import es.redsys.lib.Rest;
import es.redsys.lib.TransactionType;
import es.redsys.lib.Utils;

public class AuthenticationRestCard {
	public static void authenticationRestExample(HttpExchange exchange) throws IOException {
		Server.addCors(exchange);

		final Merchant merchant = Merchant.initWithApiKey(Secrets.REDSYS_API_KEY);
		final Parameters params = new Parameters();
		
		final Map<String, Object> receivedParams = Server.getJsonParams(exchange);
		params.setAmount(String.valueOf(receivedParams.get("amount")));
		params.setOrder(Utils.randomString(12));

        final String host = Server.getSchemeAndHost(exchange);
        if(host != null && !host.trim().isEmpty()) {
            // Notification
            params.setMerchantUrl(host + "/backend/card/notification?origin=authenticationRestExample");
        }
		
        // Card
        params.setCardNumber(receivedParams.get("cardNumber") == null ? "4548810000000003" : String.valueOf(receivedParams.get("cardNumber")));
        final String receivedExpiryDate = (receivedParams.get("expiryDate") == null ? "1249" : String.valueOf(receivedParams.get("expiryDate")));
        final String expiryDate = "" + receivedExpiryDate.charAt(2) + receivedExpiryDate.charAt(3) + receivedExpiryDate.charAt(0) + receivedExpiryDate.charAt(1);
        params.setCardExpiryDate(expiryDate.toString());
        params.setCvv2(receivedParams.get("cvv") == null ? "123" : String.valueOf(receivedParams.get("cvv")));
        
        Response initResponse = new Response();
        Parameters initParameters = null;
        try {
        	initResponse = Rest.genericInit(merchant, params, "7");
        	if(initResponse.getErrorCode() != null && !initResponse.getErrorCode().trim().isEmpty()) {
        		throw new Exception();
        	}
        	
        	initParameters = initResponse.getData();
        } catch (Exception e) {
        	Server.jsonResponse(exchange, 200, initResponse.toJsonNoAnnotations());        	
        }

		//TREAT
		final String notificationUrl = host + "/backend/challenge-response?order=" + params.getOrder() + "&protocolVersion=" + String.valueOf(initParameters.getEmv3ds().get("protocolVersion")) + "&transactionType=" + TransactionType.AUTHENTICATION + "&amount=" + params.getAmount();
		
		params.setEmv3ds(initParameters.getEmv3ds());
		params.getEmv3ds().put("threeDSInfo", "AuthenticationData");
		params.getEmv3ds().put("notificationURL", notificationUrl);
		params.getEmv3ds().put("browserAcceptHeader", exchange.getRequestHeaders().getFirst("Accept"));
		// You must obtain this from the customer's browser
		final Map<String, Object> browserDetailsEmv3ds = (HashMap<String, Object>) receivedParams.get("emv3ds");
		params.getEmv3ds().putAll(browserDetailsEmv3ds);
		
		Response response2 = new Response();
		try {
			response2 = Rest.authentication(merchant, params);
			if(response2.getErrorCode() != null && !response2.getErrorCode().trim().isEmpty()) {
				throw new Exception();
			}

	      } catch (Exception e) {
	      	Server.jsonResponse(exchange, 400, response2.toJsonNoAnnotations());        	
	      }

		if((response2.getData().getCodResponse() != null || !"0000".equals(response2.getData().getCodResponse())) && response2.getData().getEmv3ds() != null) {
			// Challenge
			response2.setChallenge(GenerateRedirectForm.challenge(merchant, response2.getData()));
		} 

		Server.jsonResponse(exchange, 200, response2.toJsonNoAnnotations());   
	}
	
	public static void authenticationConfirmationRestExample(HttpExchange exchange) throws IOException {
		Server.addCors(exchange);
		  
		final Merchant merchant = Merchant.initWithApiKey(Secrets.REDSYS_API_KEY);
		final Parameters params = new Parameters();
		
		final Map<String, String> receivedQueryParams = Server.getQueryParams(exchange);

		params.setAmount(receivedQueryParams.get("amount"));
		params.setOrder(receivedQueryParams.get("order"));

        final String host = Server.getSchemeAndHost(exchange);
        if(host != null && !host.trim().isEmpty()) {
            // Notification
            params.setMerchantUrl(host + "/backend/card/notification?origin=authenticationConfirmationRestExample");
        }
		
		Response response2 = new Response();
		try {
			response2 = Rest.authenticationConfirmation(merchant, params);			
			if(response2.getErrorCode() != null && !response2.getErrorCode().trim().isEmpty()) {
				throw new Exception();
			}
		} catch (Exception e) {
			Server.jsonResponse(exchange, 400, response2.toJsonNoAnnotations());
			return;
		}

		Server.jsonResponse(exchange, 200, response2.toJsonNoAnnotations());
	}
}
