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

import java.net.InetAddress;
import java.util.Date;

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.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.modal.OTP;
import in.gov.digilocker.uidai.logs.sender.MessageSendTaskExecutor;
import in.gov.digilocker.uidai.services.client.OTPClient;
import in.gov.digilocker.uidai.services.xmlresponse.OTPResponse;
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({ "/api" })
public class OTPController1 {
	@Autowired Validator validator;
	@Autowired DigilockerProperties properties;
	@Autowired OTPClient otpClient;
	@Autowired MessageSendTaskExecutor taskExecutor;
	private static final Logger logger = LoggerFactory.getLogger(OTPController1.class);
	

	@SuppressWarnings("deprecation")
	@PostMapping(value = { "/getotp" }, produces = { "application/json;charset=UTF-8" })
	public ResponseEntity<String> getOtp(@RequestParam(name = "transaction_id", required = false) String uniquereqid,
			@RequestParam(name = "AadhaarNumber", required = true) final String uid,
			@RequestParam(name = "type", required = false, defaultValue = "A") final String type,
			@RequestParam(name = "aadhaar_token", required = true) final String token,
			@RequestParam(name = "authtype", required = false, defaultValue = "otpauth") String authtype,
			@RequestParam(name = "consent", required = false, defaultValue = "N") String rc,
			@RequestParam(name = "key", required = false) String clientkey) {
		
		final OTP otpModel = new OTP();
		String reqTimeStamp = "";
		String[] infoArray = null;
		String maskedMobile = "";
		String maskedEmail = "";
		double reqTime = 0.0;
		double resTime = 0.0;
		String serverIP = "";
		try {
			serverIP = InetAddress.getLocalHost().getHostAddress();
			this.validator.validateToken(token);
			this.validator.validateUID(uid, type);
			authtype = this.validator.setAuthTypeForOTP(authtype);
			rc = this.validator.setResidentialConsent(rc);
			reqTimeStamp = this.validator.getCurrentDateTimeISOFormat();
			uniquereqid = this.validator.generateTransactionId(uniquereqid, uid, authtype);
			final String localApiKey = this.validator.createAPIKey(this.properties.getApiKeyDateFormat(), token);
			if (this.properties.isExceptionEnabled()) {
				OTPController1.logger.info("API Keys is:- " + localApiKey);
			}
			clientkey = "TEST";
			if (!"TEST".equals(clientkey)) {
				throw new KeyMismatchException("Invalid client key.");
			}
			otpModel.setUniqueReqId(uniquereqid);
			otpModel.setAadhaarNumber(uid);
			otpModel.setType(type);
			otpModel.setAuthType(authtype);
			otpModel.setConsent(rc);
			otpModel.setServerIP(serverIP);
			OTPController1.logger.info("Server IP is:- " + otpModel.getServerIP());
			reqTime = (double) System.currentTimeMillis();
			
			OTPResponse otpResponse = this.otpClient.sendOTPRequestToUID(otpModel, reqTimeStamp);
			
			resTime = (double) System.currentTimeMillis();
			
			infoArray = (String[]) ((otpResponse != null && "y".equalsIgnoreCase(otpResponse.getRet())) ? otpResponse.getInfo().split(",") : null);
			
			final JSONObject finalJSONResponse = new JSONObject();			
			boolean status = false;			
			String msg = "";
			otpModel.setAvgResTime((resTime - reqTime) / 1000.0);
			
			if ("y".toLowerCase().equals(otpResponse.getRet().toLowerCase())) {
				status = true;
				msg = "OTP Sent Successfully.";
				maskedMobile = infoArray[6];
				maskedEmail = infoArray[7].substring(0, infoArray[7].length() - 1);
				finalJSONResponse.put("masked_mobile", (Object) maskedMobile);
				finalJSONResponse.put("masked_email", (Object) maskedEmail);
				finalJSONResponse.put("uid_token", (Object) "");
				finalJSONResponse.put("access_token", (Object) token);
				finalJSONResponse.put("status", status);
				finalJSONResponse.put("code", (Object) otpResponse.getErr());
				finalJSONResponse.put("transaction_id", (Object) otpModel.getUniqueReqId());
				finalJSONResponse.put("msg", (Object) msg);
				otpModel.setUidToken("");
				otpModel.setResponse(otpResponse.getXmlResp());
				otpModel.setStatus(status);
				otpModel.setErrCode("");
				otpModel.setErrMsg("");
				if (this.properties.isMsgqueueEnabled()) {
					this.taskExecutor.executeTask(otpModel.toJSONObject(), "C", "otp_logs", "logs");
				}
				return new ResponseEntity<>(finalJSONResponse.toString(), HttpStatus.OK);
			}
			
			status = false;
			msg = "OTP Sent Failed.";
			maskedMobile = "";
			maskedEmail = "";
			
			finalJSONResponse.put("masked_mobile", (Object) maskedMobile);
			finalJSONResponse.put("masked_email", (Object) maskedEmail);
			finalJSONResponse.put("status", status);
			finalJSONResponse.put("access_token", (Object) token);
			finalJSONResponse.put("uid_token", (Object) "");
			finalJSONResponse.put("code", (Object) otpResponse.getErr());
			finalJSONResponse.put("transaction_id", (Object) otpModel.getUniqueReqId());
			finalJSONResponse.put("msg", (Object) msg);
			
			otpModel.setUidToken("");
			otpModel.setResponse(otpResponse.getXmlResp());
			otpModel.setStatus(status);
			otpModel.setErrCode(otpResponse.getErr());
			otpModel.setErrMsg(msg);
			
			if (this.properties.isMsgqueueEnabled()) {
				this.taskExecutor.executeTask(otpModel.toJSONObject(), "C", "otp_logs", "logs");
			}
			
			return new ResponseEntity<>(finalJSONResponse.toString(), HttpStatus.EXPECTATION_FAILED);
		} catch (RuntimeException e) {
			OTPController1.logger.error("Runtime Exception in sending OTP:- " + e.getMessage());
			boolean status = false;
			final JSONObject jsonObject = new JSONObject();
			jsonObject.put("status", status);
			jsonObject.put("access_token", (Object) token);
			jsonObject.put("err_code", 102);
			jsonObject.put("err_msg", (Object) e.getMessage());
			jsonObject.put("transaction_id", (Object) otpModel.getUniqueReqId());
			jsonObject.put("uid_token", (Object) "");
			jsonObject.put("response", (Object) "");
			otpModel.setUniqueReqId(uniquereqid);
			otpModel.setUidToken("");
			otpModel.setAadhaarNumber(uid);
			otpModel.setType(type);
			otpModel.setAuthType(authtype);
			otpModel.setConsent(rc);
			otpModel.setStatus(status);
			otpModel.setResponse("");
			otpModel.setAvgResTime(0.0);
			otpModel.setErrCode("102");
			otpModel.setErrMsg(e.getMessage());
			if (this.properties.isMsgqueueEnabled()) {
				this.taskExecutor.executeTask(otpModel.toJSONObject(), "C", "otp_logs", "logs");
			}
			return new ResponseEntity<>(jsonObject.toString(), HttpStatus.METHOD_FAILURE);
		} catch (Exception e2) {
			OTPController1.logger.error("Main Exception in sending OTP:- " + e2.getMessage());
			boolean status = false;
			final JSONObject jsonObject = new JSONObject();
			jsonObject.put("status", status);
			jsonObject.put("err_code", 101);
			jsonObject.put("err_msg", (Object) e2.getMessage());
			jsonObject.put("transaction_id", (Object) otpModel.getUniqueReqId());
			jsonObject.put("uid_token", (Object) "");
			jsonObject.put("access_token", (Object) token);
			jsonObject.put("response", (Object) "");
			otpModel.setUniqueReqId(uniquereqid);
			otpModel.setUidToken("");
			otpModel.setAadhaarNumber(uid);
			otpModel.setType(type);
			otpModel.setAuthType(authtype);
			otpModel.setConsent(rc);
			otpModel.setStatus(status);
			otpModel.setResponse("");
			otpModel.setAvgResTime(0.0);
			otpModel.setErrCode("101");
			otpModel.setErrMsg(e2.getMessage());
			
			if (this.properties.isMsgqueueEnabled()) {
				this.taskExecutor.executeTask(otpModel.toJSONObject(), "C", "otp_logs", "logs");
			}
			
			return new ResponseEntity<>(jsonObject.toString(), HttpStatus.METHOD_FAILURE);
		}
	}

	@GetMapping(value = { "/getotp" }, produces = { "application/json;charset=UTF-8" })
	public String otpHome() {
		final JSONObject jsonObject = new JSONObject();
		try {
			jsonObject.put("code", -1);
			jsonObject.put("status", false);
			jsonObject.put("response", (Object) "Get method not allowed here.");
			jsonObject.put("date", (Object) new Date());
		} catch (JSONException e) {
			e.printStackTrace();
			jsonObject.put("code", -1);
			jsonObject.put("status", false);
			jsonObject.put("response", (Object) e.getLocalizedMessage());
			jsonObject.put("date", (Object) new Date());
		}
		return jsonObject.toString();
	}
}