package in.gov.digilocker.uidai.web.controller.v2;

import java.net.Inet4Address;
import java.util.Date;
import java.util.Map.Entry;

import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import in.gov.digilocker.uidai.logs.constants.DemoAuthCollection;
import in.gov.digilocker.uidai.logs.modal.DemoAuth;
import in.gov.digilocker.uidai.logs.sender.MessageSendTaskExecutor;
import in.gov.digilocker.uidai.services.client.DemoAuthClient;
import in.gov.digilocker.uidai.services.properties.UidaiErrors;
import in.gov.digilocker.uidai.services.xmlresponse.AuthResponse;
import in.gov.digilocker.uidai.web.exceptions.KeyMismatchException;
import in.gov.digilocker.uidai.web.properties.DigilockerProperties;
import in.gov.digilocker.uidai.web.validator.Validator;

@RestController
@RequestMapping(value = "/api")
public class DemoAuthController {
	private static final Logger logger = LoggerFactory.getLogger(DemoAuthController.class);
	@Autowired Validator validator;
	@Autowired DigilockerProperties properties;	
	@Autowired DemoAuthClient demoAuthClient;
	@Autowired MessageSendTaskExecutor taskExecutor;
	@Autowired UidaiErrors uidaiErrors;

	@SuppressWarnings("deprecation")
	@PostMapping(value = "/getdemoauth/v2", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
	public ResponseEntity<String> demoAuthPost(@RequestParam(name = "uid", required = true) String uid,
			@RequestParam(name = "fullname", required = true) String personName,
			@RequestParam(name = "gender", required = true) String personGender,
			@RequestParam(name = "dob", required = true) String personDob,
			@RequestParam(name = "phone", required = false) String phone,
			@RequestParam(name = "pin", required = false) String pincode,
			@RequestParam(name = "aadhaar_token", required = true) String token,
			@RequestParam(name = "transaction_id", required = false) String uniquereqid,
			@RequestParam(name = "consent", required = false, defaultValue = "N") String consent,
			@RequestParam(name = "type", required = false, defaultValue = "A") String type,
			@RequestParam(name = "authtype", required = false, defaultValue = "demoauth") String authtype,
			@RequestParam(name = "key", required = false, defaultValue = "TEST") String clientkey) {
		
		String[] infoArray= null;
		String uidToken= "";
		String reqTimeStamp = "";
	    double reqTime = 0.0D;
	    double resTime = 0.0D;
	    DemoAuth demoAuth= new DemoAuth();
	    String serverIP= "";
	    try {
	    	serverIP= Inet4Address.getLocalHost().getHostAddress();
	    	reqTimeStamp= validator.getCurrentDateTimeISOFormat();
	    	authtype= validator.setAuthTypeForDemoAuth(authtype);
	    	consent= validator.setResidentialConsent(consent);
	    	uniquereqid= validator.generateTransactionId(uniquereqid, uid, authtype);
	    	validator.validateToken(token);
	    	validator.validateUID(uid, type);
	    	validator.validatePersonName(personName);
	    	validator.validatePersonGender(personGender);
	    	validator.validatePersonDOB(personDob);	    	
	    	if (!"TEST".equals(clientkey)) {
	    		throw new KeyMismatchException("Invalid API key.");
	    	}
	    	demoAuth.setUniqueReqId(uniquereqid);
	    	demoAuth.setAadhaarNumber(uid);
	    	demoAuth.setFullname(personName);
	    	demoAuth.setGender(personGender);
	    	demoAuth.setDob(personDob);
	    	demoAuth.setPhone((phone != null) && (!"".equals(phone)) ? phone : "");
	        demoAuth.setPin((pincode != null) && (!"".equals(pincode)) ? pincode : "");
	        demoAuth.setType(type);
	        demoAuth.setAuthType(authtype);
	        demoAuth.setConsent(consent);
	        demoAuth.setServerIP(serverIP);
	        
	        reqTime= System.currentTimeMillis();	        
	        AuthResponse demoAuthRes= demoAuthClient.validateDetailsUsingDemographicDetails(demoAuth, reqTimeStamp);	        
	        resTime= System.currentTimeMillis();
	        
	        String code= "";
	        String msg= "";	        
	        boolean status= false;
	        
	        infoArray = (null!= demoAuthRes) && (!"".equalsIgnoreCase(demoAuthRes.getInfo())) ? demoAuthRes.getInfo().split(",") : null;
			uidToken= (null!= infoArray) ? infoArray[0].substring(3, infoArray[0].length()).trim(): "";
	        
	        demoAuth.setAvgResTime((resTime-reqTime)/1000D);
	        demoAuth.setUidToken(uidToken);
	        
	        JSONObject jsonObject= new JSONObject();	        
	        if(null!= demoAuthRes &&  "y".equalsIgnoreCase(demoAuthRes.getRet())) {
	        	status= true;
	        	msg= "Your Authentication is Successful.";
	        	demoAuth.setErrCode(demoAuthRes.getErr());
	        	demoAuth.setErrMsg("");
	        	demoAuth.setStatus(status);
	        	demoAuth.setResponse("");
	        	
	        	jsonObject.put("uid_token", uidToken);
	        	jsonObject.put("code", "");
	        	jsonObject.put("status", status);
	        	jsonObject.put("transaction_id", uniquereqid);
	        	jsonObject.put("access_token", token);
	        	jsonObject.put("msg", msg);
	        	
	        	if (this.properties.isMsgqueueEnabled()) {
	        		taskExecutor.executeTask(demoAuth.toJSONObject(), "C", DemoAuthCollection.DEMO_AUTH_COLLECTION_NAME, DemoAuthCollection.DEMO_AUTH_DATABASE_NAME);
	        	}	        	
	        	return new ResponseEntity<String>(jsonObject.toString(), HttpStatus.OK);
	        }
	        status= false;
	        for (Entry<String, String> entry : uidaiErrors.getErrorMap().entrySet()) {
				if (entry.getKey().equals(demoAuthRes.getErr())) {
					code = demoAuthRes.getErr();
					msg = entry.getValue();
				}
			}        	
        	demoAuth.setErrCode(code);
        	demoAuth.setErrMsg(msg);
        	demoAuth.setStatus(status);
        	demoAuth.setResponse(demoAuthRes.getXmlResp());
        	
        	jsonObject.put("uid_token", uidToken);
        	jsonObject.put("access_token", token);
        	jsonObject.put("transaction_id", uniquereqid);
        	jsonObject.put("status", status);
        	jsonObject.put("code", code);
        	jsonObject.put("msg", msg);
        	if (this.properties.isMsgqueueEnabled()) {
        		taskExecutor.executeTask(demoAuth.toJSONObject(), "C", DemoAuthCollection.DEMO_AUTH_COLLECTION_NAME, DemoAuthCollection.DEMO_AUTH_DATABASE_NAME);
        	}
        	
        	return new ResponseEntity<String>(jsonObject.toString(), HttpStatus.EXPECTATION_FAILED);	        
	    } catch (RuntimeException e) {
	    	logger.error("Runtime Exception in demo auth home:- " +e.getLocalizedMessage());
	    	JSONObject jsonObject= new JSONObject();
	    	jsonObject.put("uid_token", "");        	
        	jsonObject.put("status", false);
        	jsonObject.put("transaction_id", uniquereqid);
        	jsonObject.put("access_token", token);
        	jsonObject.put("code", "RUNTIME-102");
        	jsonObject.put("msg", e.getMessage());
	    	
        	demoAuth.setUniqueReqId(null!=uniquereqid && !"".equals(uniquereqid)? uniquereqid: "");
        	demoAuth.setUidToken("");
	    	demoAuth.setAadhaarNumber(uid);
	    	demoAuth.setFullname(personName);
	    	demoAuth.setGender(personGender);
	    	demoAuth.setDob(personDob);
	    	demoAuth.setPhone((phone != null) && (!"".equals(phone)) ? phone : "");
	        demoAuth.setPin((pincode != null) && (!"".equals(pincode)) ? pincode : "");
	        demoAuth.setType(type);
	        demoAuth.setAuthType(authtype);
	        demoAuth.setConsent(consent);
	        demoAuth.setAvgResTime(0.0);
	        demoAuth.setErrCode("RUNTIME-102");
        	demoAuth.setErrMsg(e.getLocalizedMessage());
        	demoAuth.setStatus(false);
        	demoAuth.setResponse("");        	
        	
        	if (this.properties.isMsgqueueEnabled()) {
        		taskExecutor.executeTask(demoAuth.toJSONObject(), "C", DemoAuthCollection.DEMO_AUTH_COLLECTION_NAME, DemoAuthCollection.DEMO_AUTH_DATABASE_NAME);
        	}
        	
        	return new ResponseEntity<String>(jsonObject.toString(), HttpStatus.METHOD_FAILURE);
		
	    } catch (Exception e) {
			logger.error("MAIN Exception in demo auth home:- " +e.getLocalizedMessage());
			JSONObject jsonObject= new JSONObject();
			jsonObject.put("transaction_id", uniquereqid);
	    	jsonObject.put("uid_token", "");
	    	jsonObject.put("status", false);
	    	jsonObject.put("code", "MAIN-102");        	
        	jsonObject.put("access_token", token);
        	jsonObject.put("msg", e.getMessage());
			
        	demoAuth.setUniqueReqId(null!=uniquereqid && !"".equals(uniquereqid)? uniquereqid: "");
        	demoAuth.setUidToken("");
	    	demoAuth.setAadhaarNumber(uid);
	    	demoAuth.setFullname(personName);
	    	demoAuth.setGender(personGender);
	    	demoAuth.setDob(personDob);
	    	demoAuth.setPhone((phone != null) && (!"".equals(phone)) ? phone : "");
	        demoAuth.setPin((pincode != null) && (!"".equals(pincode)) ? pincode : "");
	        demoAuth.setType(type);
	        demoAuth.setAuthType(authtype);
	        demoAuth.setConsent(consent);
	        demoAuth.setAvgResTime(0.0);
	        demoAuth.setErrCode("MAIN-102");
        	demoAuth.setErrMsg(e.getLocalizedMessage());
        	demoAuth.setStatus(false);
        	demoAuth.setResponse("");
        	
        	if (this.properties.isMsgqueueEnabled()) {
        		taskExecutor.executeTask(demoAuth.toJSONObject(), "C", DemoAuthCollection.DEMO_AUTH_COLLECTION_NAME, DemoAuthCollection.DEMO_AUTH_DATABASE_NAME);
        	}
        	
        	return new ResponseEntity<String>(jsonObject.toString(), HttpStatus.METHOD_FAILURE);
		}
	}


	@GetMapping(value = "/getdemoauth/v2", produces = MediaType.APPLICATION_JSON_VALUE)
	public String getAuth() {
		JSONObject jsonObject = new JSONObject();
		try {
			jsonObject.put("code", -1);
			jsonObject.put("status", false);
			jsonObject.put("response", "Get method not allowed here.");
			jsonObject.put("date", new Date());
		} catch (JSONException e) {
			logger.error("Exception auth home:- " + e.getLocalizedMessage());
			jsonObject.put("code", -1);
			jsonObject.put("status", false);
			jsonObject.put("response", e.getLocalizedMessage());
			jsonObject.put("date", new Date());
		}
		return jsonObject.toString();
	}
}
