/*
 * 
 */
package com.bankaudit.rest.controller;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;

import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.bankaudit.constants.BankAuditConstant;
import com.bankaudit.dto.DataTableResponse;
import com.bankaudit.model.RiskScorePercentage;
import com.bankaudit.model.RiskScorePercentageWrk;
import com.bankaudit.service.BusinessDateService;
import com.bankaudit.service.RiskScorePercentageService;
import com.bankaudit.util.BankAuditUtil;
import com.bankaudit.util.ServiceStatus;


/**
 * The Class {@link RiskScorePercentageController} provides the REST services to
 * manage the {@link RiskScorePercentage} class objects .
 *
 * @author amit.patel
 * @version 1.0
 */


@RestController

@RequestMapping("/api/riskScorePercentage")
public class RiskScorePercentageController {


	/**
	 * The risk score percentage service is autowired and make methods available
	 * from service layer .
	 */
	@Autowired
	RiskScorePercentageService riskScorePercentageService;
	
	/**
	 * The business date service is autowired and make methods available from
	 * service layer .
	 */
	@Autowired
	BusinessDateService businessDateService;
	
	/** The Constant logger is used to specify the . */
	@Autowired
	
	static final Logger logger = Logger.getLogger(RiskScorePercentageController.class);
	
	/**
	 * This method is use to Creates the risk score percentage.
	 *
	 * @param riskScorePercentages
	 *            specify the risk score percentages
	 * @return the service status class object with response status and payload
	 *         .
	 */
	
@RequestMapping(method=RequestMethod.POST,consumes=MediaType.APPLICATION_JSON_VALUE,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus createRiskScorePercentage(@RequestBody List<RiskScorePercentage> riskScorePercentages){
		ServiceStatus serviceStatus=new ServiceStatus();
		
		if(riskScorePercentages!=null && !riskScorePercentages.isEmpty()){
			try{
			
			int size = riskScorePercentages.size();
			int allRangeCoveredVerify=0;  // to verify that all the numbers from 0 to 100 covered or not.
			boolean val =true, validation=true, rangeCovered =true;
			for(int j=0; j<size; j++){
				if(!riskScorePercentages.get(j).getStatus().equalsIgnoreCase("D") && val != false){  // Skip status "D" records, as they are not considered for evaluation 
					int mino=riskScorePercentages.get(j).getMinimunPer();
					int maxo=riskScorePercentages.get(j).getMaximumPer();
					allRangeCoveredVerify += maxo - mino;
					System.out.println(j +"====================== is -- :: MIN = " +mino  + " MAX = " +maxo + "RangeCovered ::"+ allRangeCoveredVerify); 
					if(mino < 0 || maxo > 100) {
						val = false; validation =false;
					}
					
					for(int k=j+1; k <size; k++){
						int mini=riskScorePercentages.get(k).getMinimunPer();
						int maxi=riskScorePercentages.get(k).getMaximumPer();
						
						System.out.println(j +" is :: MINi = " +mini  + " MAXi = " +maxi);
						if( ((mino < maxo) && (maxo <= mini) && (mini < maxi)) || ((mini < maxi) && (maxi <= mino) && (mino < maxo))) 
							System.out.println("mino maxo mini maxi :: "+ mino +" "+ maxo +" " + mini + " " + maxi);
						else {
							System.out.println("Validation failed ");
							val = false; validation =false;
							break;
						}
						
					}if(!val) break;
					riskScorePercentages.get(j).setBusinessdateTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(riskScorePercentages.get(j).getLegalEntityCode()));
					riskScorePercentages.get(j).setSysdateTimestamp(new Timestamp(System.currentTimeMillis()));
					riskScorePercentages.get(j).setMakerTimestamp(riskScorePercentages.get(j).getBusinessdateTimestamp());
				}
			}
			if(allRangeCoveredVerify != 100) { // This is to verify all the Range from 0 to 100 covered or not.
				val=false; rangeCovered =false;
			}
			System.out.println("allRangeCoveredVerify ::"+ allRangeCoveredVerify);
		
		if(val){
			
			/************************ Logic to give ranking to the Ratings Internally *******************************/
			Collections.sort(riskScorePercentages);
			int ranking=1;
			for(RiskScorePercentage rskPrc: riskScorePercentages) {
				System.out.println("Min prc...................................."+rskPrc.getMinimunPer());
				rskPrc.setRatingInternal(ranking++);
			}
			/***********Ranking Logic, ends here ***************/
			
			riskScorePercentageService.createRiskScorePercentage(riskScorePercentages);
			serviceStatus.setStatus("success");
			serviceStatus.setMessage("successfully created");
		}else {
			serviceStatus.setStatus("failure");
			System.out.println("RangeCovered ::"+ rangeCovered +" validate:: "+validation);
			if(!validation)	serviceStatus.setMessage("Please provide the valid range ");
			else serviceStatus.setMessage("Please cover all the possible ranges from 0 to 100 ");
		}
			
		} catch (Exception e) {
			e.printStackTrace();
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("failure");
			if(e instanceof org.springframework.dao.DataIntegrityViolationException) {
				serviceStatus.setMessage("DATAINTGRTY_VIOLATION");
			}
		}

		}else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("invalid payload");
		}
		
		return serviceStatus;
	}
	
	/**
	 * This method is use to Update risk score percentage.
	 *
	 * @param riskScorePercentages
	 *            specify the risk score percentages
	 * @return the service status class object with response status and payload
	 *         .
	 */
	
@RequestMapping(method=RequestMethod.PUT,consumes=MediaType.APPLICATION_JSON_VALUE,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus updateRiskScorePercentage(@RequestBody List<RiskScorePercentage> riskScorePercentages){
		ServiceStatus serviceStatus=new ServiceStatus();
		
		if(riskScorePercentages!=null
				&& !riskScorePercentages.isEmpty()
				){
			
			try{
				
				int size = riskScorePercentages.size();
				int allRangeCoveredVerify=0;  // to verify that all the numbers from 0 to 100 covered or not.
				boolean val =true, validation=true, rangeCovered =true;
				
				for(int j=0; j<size; j++){
					if(!riskScorePercentages.get(j).getStatus().equalsIgnoreCase("D") && val != false){   // Skip status "D" records, as they are not considered for evaluation 
						int mino=riskScorePercentages.get(j).getMinimunPer();
						int maxo=riskScorePercentages.get(j).getMaximumPer();
						allRangeCoveredVerify += maxo - mino;
						
						if(mino < 0 || maxo > 100) {
							val = false; validation =false;
						}
						
						System.out.println(j +"============== is :: MIN = " +mino  + " MAX = " +maxo);
						for(int k=j+1; k <size; k++){
								int mini=riskScorePercentages.get(k).getMinimunPer();
								int maxi=riskScorePercentages.get(k).getMaximumPer();
								
								if(!riskScorePercentages.get(k).getStatus().equalsIgnoreCase("D")){
									if( ((mino < maxo) && (maxo <= mini) && (mini < maxi)) || ((mini < maxi) && (maxi <= mino) && (mino < maxo))) 
										System.out.println("mino maxo mini maxi :: "+ mino +" "+ maxo +" " + mini + " " + maxi);
									else {
										System.out.println("Validation failed ");
										val = false;
										break;
									}
								}
								
							}if(!val) break;
							riskScorePercentages.get(j).setBusinessdateTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(riskScorePercentages.get(j).getLegalEntityCode()));
							riskScorePercentages.get(j).setSysdateTimestamp(new Timestamp(System.currentTimeMillis()));
							
							if(riskScorePercentages.get(j).getStatus().equals(BankAuditConstant.STATUS_AUTH)){
								riskScorePercentages.get(j).setCheckerTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(riskScorePercentages.get(j).getLegalEntityCode()));
							}else{
								riskScorePercentages.get(j).setMakerTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(riskScorePercentages.get(j).getLegalEntityCode()));
							}
						}
				}
				
				if(allRangeCoveredVerify != 100) { // This is to verify all the Range from 0 to 100 covered or not.
					val=false; rangeCovered =false;
				}
				System.out.println("RangeCovered ::"+ allRangeCoveredVerify);
		
			if(val){
				/************************ Logic to give ranking to the Ratings Internally *******************************/
				Collections.sort(riskScorePercentages);
				int ranking=1;
				for(RiskScorePercentage rskPrc: riskScorePercentages) {
					System.out.println("Min prc...................................."+rskPrc.getMinimunPer());
					rskPrc.setRatingInternal(ranking++);
				}
				/***********Ranking Logic, ends here ***************/
				
				riskScorePercentageService.updateRiskScorePercentages(riskScorePercentages);
				serviceStatus.setStatus("success");
				serviceStatus.setMessage("successfully updated");
			}else {
				serviceStatus.setStatus("failure");
				if(!validation)	serviceStatus.setMessage("Please provide the valid range ");
				else serviceStatus.setMessage("Please cover all the possible ranges from 0 to 100 ");
			}
			
		} catch (Exception e) {
			e.printStackTrace();
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("failure");
			if(e instanceof org.springframework.dao.DataIntegrityViolationException) {
				serviceStatus.setMessage("DATAINTGRTY_VIOLATION");
			}
		}

		}else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("invalid payload");
		}
		
		return serviceStatus;
	}
	
	/**
	 * This method is use to Gets the risk score percentage.
	 *
	 * @param legalEntityCode
	 *            specify the legal entity code
	 * @param riskCategoryCode
	 *            specify the risk category code
	 * @param auditTypeCode
	 *            specify the audit type code
	 * @param status
	 *            specify the status
	 * @return the service status class object with response status and payload
	 *         .
	 */
	
@RequestMapping(value="/getByLegalEntityCodeAndRiskCategoryCodeAndAuditTypeCode/{legalEntityCode}/{riskCategoryCode}/{auditTypeCode}/{status}",method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus getRiskScorePercentage(@PathVariable("legalEntityCode")Integer legalEntityCode,
			@PathVariable("riskCategoryCode") String riskCategoryCode,
			@PathVariable("auditTypeCode") String auditTypeCode,
			@PathVariable("status") String status
			){
		ServiceStatus serviceStatus=new ServiceStatus();
		
		if(legalEntityCode!=null 
				&& !BankAuditUtil.isEmptyString(riskCategoryCode)
				&& !BankAuditUtil.isEmptyString(auditTypeCode)){
			
			try {
			    RiskScorePercentage riskScorePercentage=riskScorePercentageService.getRiskScorePercentage(legalEntityCode,riskCategoryCode,auditTypeCode,status);
			    if(riskScorePercentage!=null){
			    	serviceStatus.setResult(riskScorePercentage);
				    serviceStatus.setStatus("success");
				    serviceStatus.setMessage("successfully retrieved ");	
			    }else {
					serviceStatus.setStatus("failure");
					serviceStatus.setMessage("RiskScorePercentage not found");
				}
				
			} catch (Exception e) {
				e.printStackTrace();
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
			}
			
		}else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("invalid payload ");
		}
		
		return serviceStatus;
	}
	

	
	/**
	 * This method is use to Gets the risk score percentages.
	 *
	 * @param drawStr
	 *            specify the draw str
	 * @param length
	 *            specify the length
	 * @param start
	 *            specify the start
	 * @param search
	 *            specify the search
	 * @param orderColumnStr
	 *            specify the order column str
	 * @param orderDirection
	 *            specify the order direction
	 * @param legalEntityCodeStr
	 *            specify the legal entity code str
	 * @return the data table response class object with response status and
	 *         payload .
	 */
	
@RequestMapping(value="/getAll",method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE) 
	DataTableResponse getRiskScorePercentages(
			@RequestParam("draw") String drawStr,
			@RequestParam("length") String length,
			@RequestParam("start") String start,
			@RequestParam("search[value]") String search,
			@RequestParam("order[0][column]") String orderColumnStr,
			@RequestParam("order[0][dir]")String orderDirection,
			@RequestParam("legalEntityCode")String legalEntityCodeStr){
		
		DataTableResponse dataTableResponse=null;
		
		if(!BankAuditUtil.isEmptyString(drawStr)
				&& !BankAuditUtil.isEmptyString(length)
				&& !BankAuditUtil.isEmptyString(start)
				&& !BankAuditUtil.isEmptyString(legalEntityCodeStr)){
			try {
				Integer legalEntityCode=Integer.parseInt(legalEntityCodeStr);
				Integer draw=Integer.parseInt(drawStr);
				Integer size=Integer.parseInt(length);
				Integer page=Integer.parseInt(start)/size;
				Integer orderColumn=null;
				if(!BankAuditUtil.isEmptyString(orderColumnStr)){
					orderColumn=Integer.parseInt(orderColumnStr);
				}
				dataTableResponse = riskScorePercentageService.getRiskScorePercentages(legalEntityCode,search,orderColumn,orderDirection,page,size);
				dataTableResponse.setDraw(draw);    
					
			} catch (Exception e) {
                dataTableResponse=new DataTableResponse();
                dataTableResponse.setError(e.getMessage());
				e.printStackTrace();
			}
		
		}else {
			dataTableResponse=new DataTableResponse();
			dataTableResponse.setError("invalid data");
		}
		
		return dataTableResponse;
	}
	
	
	/**
	 * This method is use to Gets the risk score percentagefor update.
	 *
	 * @param legalEntityCode
	 *            specify the legal entity code
	 * @param auditTypeCode
	 *            specify the audit type code
	 * @param status
	 *            specify the status
	 * @return the service status class object with response status and payload
	 *         .
	 */
	
@RequestMapping(value="/getByLegalEntityCodeAndAuditTypeCode/{legalEntityCode}/{auditTypeCode}/{status}",method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus getRiskScorePercentageforUpdate(@PathVariable("legalEntityCode")Integer legalEntityCode,
			@PathVariable("auditTypeCode") String auditTypeCode,
			@PathVariable("status") String status
			){
		ServiceStatus serviceStatus=new ServiceStatus();
		
		if(legalEntityCode!=null 
				&& !BankAuditUtil.isEmptyString(auditTypeCode)){
			
			try {
				System.out.println("Inside getRiskScorePercentageforUpdate ....."+ legalEntityCode +" :: "+auditTypeCode);
			    List<RiskScorePercentage> riskScorePercentageList=riskScorePercentageService.getRiskScorePercentageforUpdate(legalEntityCode,auditTypeCode, status);
			    if(riskScorePercentageList!=null){
			    	serviceStatus.setResult(riskScorePercentageList);
				    serviceStatus.setStatus("success");
				    serviceStatus.setMessage("successfully retrieved ");	
			    }else {
					serviceStatus.setStatus("failure");
					serviceStatus.setMessage("RiskScorePercentage not found");
				}
				
			} catch (Exception e) {
				e.printStackTrace();
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
			}
			
		}else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("invalid payload ");
		}
		return serviceStatus;
	}


	/**
	 * This method is use to Checks if is risk score percentage.
	 *
	 * @param legalEntityCode
	 *            specify the legal entity code
	 * @param auditTypeCode
	 *            specify the audit type code
	 * @return the service status class object with response status and payload
	 *         .
	 */
	
@RequestMapping(value="/isRiskScorePercentage/{legalEntityCode}/{auditTypeCode}",method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus isRiskScorePercentage(@PathVariable("legalEntityCode")Integer legalEntityCode,
			@PathVariable("auditTypeCode") String auditTypeCode
			){
		ServiceStatus serviceStatus=new ServiceStatus();
		
		if(legalEntityCode!=null 
				&& !BankAuditUtil.isEmptyString(auditTypeCode)){
			
			try {
		    	serviceStatus.setResult(riskScorePercentageService.isRiskScorePercentage(legalEntityCode,auditTypeCode));
			    serviceStatus.setStatus("success");
			    serviceStatus.setMessage("successfully retrieved ");	
		    
				
			} catch (Exception e) {
				e.printStackTrace();
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
			}
			
		}else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("invalid payload ");
		}
		
		return serviceStatus;
	}

	
@RequestMapping(value="/isRiskCategoryCode",method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus isRiskCategoryCode(@RequestParam("legalEntityCode")Integer legalEntityCode,
			@RequestParam("auditTypeCode") String auditTypeCode,
			@RequestParam("riskCategoryCode") String riskCategoryCode
			){
		ServiceStatus serviceStatus=new ServiceStatus();
		
		if(legalEntityCode!=null 
				&& !BankAuditUtil.isEmptyString(auditTypeCode)
				&& !BankAuditUtil.isEmptyString(riskCategoryCode)){
			
			try {
		    	serviceStatus.setResult(riskScorePercentageService.isRiskCategoryCode(legalEntityCode,auditTypeCode,riskCategoryCode));
			    serviceStatus.setStatus("success");
			    serviceStatus.setMessage("successfully retrieved ");	
		    
				
			} catch (Exception e) {
				e.printStackTrace();
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
			}
			
		}else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("invalid payload ");
		}
		
		return serviceStatus;
	}
	
	
@RequestMapping(value="/getRiskCategoryOnPercentage/{legalEntityCode}/{auditTypeCode}/{riskScore}",method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus getRiskCategoryOnPercentage(@PathVariable("legalEntityCode")Integer legalEntityCode,
			@PathVariable("auditTypeCode") String auditTypeCode,@PathVariable("riskScore") Integer riskScore
			){
		ServiceStatus serviceStatus=new ServiceStatus();
		
		if(legalEntityCode!=null && riskScore != null && !BankAuditUtil.isEmptyString(riskScore.toString()) && !BankAuditUtil.isEmptyString(auditTypeCode)){
			
			try {
		    	serviceStatus.setResult(riskScorePercentageService.getRiskCategoryOnPercentage(legalEntityCode,auditTypeCode,riskScore));
			    serviceStatus.setStatus("success");
			    serviceStatus.setMessage("successfully retrieved ");	
		    
				
			} catch (Exception e) {
				e.printStackTrace();
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
			}
			
		}else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("invalid payload ");
		}
		
		return serviceStatus;
	}


}
