package com.bankaudit.rest.process.service;

import java.sql.Timestamp;
import java.time.LocalDate;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.bankaudit.constants.BankAuditConstant;
import com.bankaudit.dto.DataTableResponse;
import com.bankaudit.dto.EntityAuditDataDto;
import com.bankaudit.dto.process.AuditDto;
import com.bankaudit.process.model.AuditActionItem;
import com.bankaudit.process.model.AuditLetterUserInputsWrk;
import com.bankaudit.process.model.AuditRating;
import com.bankaudit.process.model.AuditSchedule;
import com.bankaudit.process.model.AuditScheduleStagesStatusHst;
import com.bankaudit.process.model.AuditScheduleStatus;
import com.bankaudit.process.model.AuditTeam;
import com.bankaudit.process.model.RiskSummaryDtls;
import com.bankaudit.rest.process.dao.AuditObservationDao;
import com.bankaudit.rest.process.dao.AuditRatingParameterScoreDao;
import com.bankaudit.rest.process.dao.LettersDao;
import com.bankaudit.rest.process.dao.MyAuditsDao;
import com.bankaudit.service.BusinessDateService;
import com.bankaudit.service.MaintEntityService;
import com.bankaudit.util.BankAuditUtil;

@Service("myAuditService")
@Transactional("transactionManager")
public class MyAuditServiceImpl implements MyAuditsService{

	@Autowired(required=true)
	MyAuditsDao myAuditsDao;
	
	@Autowired
	MaintEntityService maintEntityService;
	
	@Autowired
	BusinessDateService businessDateService;
	
	@Autowired
	AuditObservationService auditObservationService;
	
	@Autowired
	AuditObservationDao auditObservationDao;
	
	@Lazy
	@Autowired
	AuditRatingParameterScoreDao auditRatingParameterScoreDao;
	
	@Autowired
	EmailService emailService;
	
	@Autowired
	LettersDao  lettersDao;
	
	@Autowired
	AuditScheduleStagesStatusHstService auditScheduleStagesStatusHstService; 
	
	static final Logger logger = Logger.getLogger(MyAuditServiceImpl.class);

	@Override
	public DataTableResponse getMuAuditsList(int legalEntityCode, String userId, String search, Integer orderColumn,
			String orderDirection, Integer page, Integer size, String role, LocalDate financialYear, String auditTypeCode) {
		List<LocalDate>  financialYearStrtEndList=null;
		if(financialYear!=null) financialYearStrtEndList= BankAuditUtil.getFinancialStartEndDatesNxtFrom(financialYear);
		DataTableResponse ds=myAuditsDao.getMuAuditsList(legalEntityCode,userId,search,orderColumn,	orderDirection,page,size, role,
				financialYear, auditTypeCode, financialYearStrtEndList);
		return ds;
	}
	
	@Override
	public DataTableResponse getAuditsForView(int legalEntityCode, String userId, String unitCode, String roleId, String search, Integer orderColumn,
			String orderDirection, Integer page, Integer size, LocalDate financialYear, String auditTypeCode) {
		List<LocalDate>  financialYearStrtEndList=null;
		if(financialYear!=null) financialYearStrtEndList= BankAuditUtil.getFinancialStartEndDatesNxtFrom(financialYear);
		DataTableResponse ds=myAuditsDao.getAuditsForView(legalEntityCode,userId,unitCode,roleId,search,orderColumn,orderDirection,page,size,
				financialYear, auditTypeCode, financialYearStrtEndList);
		return ds;
	}
	
	@Override
	public DataTableResponse getAuditsForLetter(int legalEntityCode,String userId, String search,Integer orderColumn,
			String orderDirection, Integer page, Integer size, String role, LocalDate financialYear, String auditTypeCode) {
		List<LocalDate>  financialYearStrtEndList=null;
		if(financialYear!=null) financialYearStrtEndList= BankAuditUtil.getFinancialStartEndDatesNxtFrom(financialYear);
		DataTableResponse ds=myAuditsDao.getAuditsForLetter(legalEntityCode,userId,search,orderColumn,orderDirection,page,size, role,
				financialYear, auditTypeCode, financialYearStrtEndList);
		return ds;
	}
	
	@Override
	public DataTableResponse getMyBranchAudits(int legalEntityCode, String auditId, String unitCode, String userId, String role, String search,Integer orderColumn,
			String orderDirection, Integer page, Integer size, LocalDate financialYear, String auditTypeCode) {
		List<LocalDate>  financialYearStrtEndList=null;
		if(financialYear!=null)financialYearStrtEndList= BankAuditUtil.getFinancialStartEndDatesNxtFrom(financialYear);
		DataTableResponse ds=myAuditsDao.getMyBranchAudits(legalEntityCode,auditId,unitCode,userId,role,search,orderColumn,orderDirection,page,size,
				financialYear, auditTypeCode, financialYearStrtEndList);
		return ds;
	}
	
	@Override
	public AuditSchedule getAuditByPlanIdAndAuditId(int legalEntityCode, String auditTypeCode, String planId,
			String auditId) {
		AuditSchedule auditDtls=myAuditsDao.getAuditByPlanIdAndAuditId(legalEntityCode,auditTypeCode,planId,auditId); 
		 return auditDtls; 
	}

	@Override
	public List getRatingAndObsCntGrpSGrpwiseByAuditId(int legalEntityCode, String auditTypeCode, String planId,String auditId) {
		List ratingObscntlst= null;
		ratingObscntlst=myAuditsDao.getRatingAndObsCntGrpSGrpwiseByAuditId(legalEntityCode,auditTypeCode,planId,auditId); 
		Map<String, String> processCntMap = myAuditsDao.getObsRespRvwCnt(legalEntityCode, auditTypeCode, planId, auditId);
		ratingObscntlst.add(processCntMap);
		return ratingObscntlst;
	}

	@Override
	public void updateMyAuditStatus(AuditSchedule auditSchedule) {
		myAuditsDao.updateMyAuditStatus(auditSchedule);
		logger.info("Inside updateMyAuditStatus auditStatus .."+auditSchedule.getAuditStatus());
		/******** BaaSDOS Specific **************/
		if(auditSchedule != null && "AS".equalsIgnoreCase(auditSchedule.getAuditStatus())) {
			auditObservationDao.updateAuditObservationRecordStatus(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), 
					auditSchedule.getPlanId(), auditSchedule.getAuditId(), "AS");
			updateAuditStatusDetailOnFinalize(auditSchedule);
		}else {
			//auditObservationDao.updateAuditObservationRecordStatus(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), 
					//auditSchedule.getPlanId(), auditSchedule.getAuditId(), "...");  // Updated to auditSchedule.getAuditStatus()
		}
		
		/*********** Updating all "Others" checklist to Not Applicable(NA) while Initiating ***********/ 
		// Commented as this time the Observations not inserted, the service call moved to AuditObservationController->insertUpdateAutoBulkCheckListCapture()
		/*if(auditSchedule != null && "AI".equalsIgnoreCase(auditSchedule.getAuditStatus())) {
			logger.info("Calling updatingOthersToNA ..");
			// auditObservationService.updatingOthersToNA(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), auditSchedule.getAuditId());
		}*/
		
		//Mail sending/trigger
		logger.info("Before Email sending AuditInititae/Exit/Respond/Review audit type .."+ auditSchedule.getAuditTypeCode());
		
		try {
		if(BankAuditConstant.EMAIL_INSPECTION && !"BRANCHI".equalsIgnoreCase(auditSchedule.getAuditTypeCode())) { // BRANCHI audit type Email trigger suppressed. 
			logger.info("Before sending Email in updateMyAuditStatus .."+ auditSchedule.getAuditId());
			logger.info("AuditStatus .. "+auditSchedule.getAuditStatus()+" ObsStatus .. "+auditSchedule.getObservationStatus() +" reportStatus .. "+auditSchedule.getReportStatus());
			logger.info("RespondStatus .. "+auditSchedule.getRespondStatus() +" ReviewStatus .. "+ auditSchedule.getReviewStatus() );
			if("AI".equalsIgnoreCase(auditSchedule.getAuditStatus()) && auditSchedule.getObservationStatus()==null) {
				emailService.sendInspectionInitiate(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId());
			}else if("AI".equalsIgnoreCase(auditSchedule.getAuditStatus()) && "AE".equalsIgnoreCase(auditSchedule.getObservationStatus())) {
				emailService.sendInspectionExit(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId());
			}else if("AR".equalsIgnoreCase(auditSchedule.getAuditStatus()) ) {  // || "RS".equalsIgnoreCase(auditSchedule.getRespondStatus())
				emailService.sendComplianceSubmission(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId());
			}else if("AW".equalsIgnoreCase(auditSchedule.getAuditStatus()) ) {  // || "WS".equalsIgnoreCase(auditSchedule.getReviewStatus())
				emailService.sendFurtherCompliance(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId());
			}
		}
		}catch(Exception e){
			e.printStackTrace(System.out);
		}//Mail trigger, End here
		
		/********* End here **************/
		
	}
		
	@Override
	public void updateAuditScheduleCounts(AuditSchedule auditSchedule) {
		myAuditsDao.updateAuditScheduleCounts(auditSchedule);
	}

	@Override
	public List getAuditsForDashboard(int legalEntityCode,String userId,String role,String period,String fromDate,String toDate) {
		List myAuditsLst= null;
		myAuditsLst=myAuditsDao.getAuditsForDashboard(legalEntityCode,userId,role,period,fromDate,toDate);
		return myAuditsLst;
	}


	@Override
	public DataTableResponse getAdHocAuditsForAuditor(int parseInt, String userId, String search, Integer orderColumn,
			String orderDirection, Integer page, Integer size, LocalDate financialYear, String auditTypeCode) {
		List<LocalDate>  financialYearStrtEndList=null;
		if(financialYear!=null)financialYearStrtEndList= BankAuditUtil.getFinancialStartEndDatesNxtFrom(financialYear);
		DataTableResponse ds=myAuditsDao.getAdHocAuditsForAuditor(parseInt,userId,search,orderColumn,orderDirection,page,size,
				financialYear, auditTypeCode, financialYearStrtEndList);
		return ds;
	}
	
	@Override
	public String chkAuditEarlyStartAllowed(AuditSchedule auditSchedule) {
		return myAuditsDao.chkAuditEarlyStartAllowed(auditSchedule);
		
	}


	@Override
	public DataTableResponse getAdHocAuditsForManagement(int parseInt, String userId, String search,
			Integer orderColumn, String orderDirection, Integer page, Integer size, LocalDate financialYear, String auditTypeCode) {
		List<LocalDate>  financialYearStrtEndList=null;
		if(financialYear!=null)financialYearStrtEndList= BankAuditUtil.getFinancialStartEndDatesNxtFrom(financialYear);
		DataTableResponse ds=myAuditsDao.getAdHocAuditsForManagement(parseInt,userId,search,orderColumn,orderDirection,page,size,
				financialYear, auditTypeCode, financialYearStrtEndList);
		return ds;
	}
	
	@Override
	public String isAuditObsPendingBfrAuditSubmit(AuditSchedule auditSchedule) {
		return myAuditsDao.isAuditObsPendingBfrAuditSubmit(auditSchedule);
	}
	
	@Override
	public String isAuditObsPending(AuditDto auditDto, String status) {
		return myAuditsDao.isAuditObsPending(auditDto, status);
	}
	
	@Override
	public String isAuditReviewPending(AuditDto auditDto, String status) {
		return myAuditsDao.isAuditReviewPending(auditDto, status);
	}
	
	@Override
	public List getAuditDetailsForReport(int legalEntityCode,String userId,String role,String auditId,String planId,String auditTypeCode) {
		List myAuditDetails= null;
		myAuditDetails=myAuditsDao.getAuditDetailsForReport(legalEntityCode,userId,role,auditId,planId,auditTypeCode);
		return myAuditDetails;
	}
	
	@Override
	public List getAuditObservationDetailsForReport(int legalEntityCode,String userId,String role,String auditId,String planId,String auditTypeCode) {
		List myAuditObservationDetails= null;
		myAuditObservationDetails=myAuditsDao.getAuditObservationDetailsForReport(legalEntityCode,userId,role,auditId,planId,auditTypeCode);
		return myAuditObservationDetails;
	}
	
	@Override
	public Boolean getFetchObservationsExtrnlAndInsertInternal(int legalEntityCode,String userId,String unitId,String auditId,String planId,String auditTypeCode) {
		Boolean fetchInsertStatus= false;
		fetchInsertStatus=myAuditsDao.getFetchObservationsExtrnlAndInsertInternal(legalEntityCode,userId,unitId,auditId,planId,auditTypeCode);
		return fetchInsertStatus;
	}
	
	@Override
	public String getAlreadyFetchObsStatus(int legalEntityCode,String userId,String auditId,String planId,String auditTypeCode) {
		String fetchInsertStatus=myAuditsDao.getAlreadyFetchObsStatus(legalEntityCode,userId,auditId,planId,auditTypeCode);
		return fetchInsertStatus;
	}
	
	@Override
	public DataTableResponse getAuditsOnDashboard(int legalEntityCode, String userId, String search, Integer orderColumn,
			String orderDirection, Integer page, Integer size, String auditStatus, String auditTypeCode) {
		
		List<String> unitsList = null;
		List<String> auditList = null;
  		String unitsListToConcatinatedString="";
  		LocalDate fromDate=null, toDate=null;
  		
  		try {
	  		//To get the List of Units, Jurisdictions wise
			unitsList=maintEntityService.getSubBranchesGyUserIdOrUnitId(legalEntityCode,"user",userId);
				logger.info("unitsList .."+ unitsList);
				
				if(unitsList!=null&&!unitsList.isEmpty()){ 
					for (String unitId : unitsList) {
						if(unitsListToConcatinatedString.length()==0) 
							unitsListToConcatinatedString="'"+unitId+"'";	
						unitsListToConcatinatedString+=",'"+unitId+"'";	
					}
				logger.info("unitsListToConcatinatedString .."+ unitsListToConcatinatedString);
				//End here
				}
		}catch(Exception e) {
		}
  		try {
  			Date businessDate =businessDateService.getBusinessDateTimestampByLegalEntityCode(legalEntityCode);
  			logger.info("businessDate .... "+ businessDate);
  			Calendar calendar=Calendar.getInstance();
  			calendar.setTime(businessDate);
  			
  			
  			Integer year=null;
  			if( calendar.get(Calendar.MONTH)>=4){
  				year=calendar.get(Calendar.YEAR);
  			}else{
  				year=calendar.get(Calendar.YEAR)-1;
  			}
  			fromDate=LocalDate.of(year, 4, 1);
  			toDate=fromDate.plusMonths(12).minusDays(1);
  			logger.info(" fromDate .."+ fromDate + " toDate .."+toDate);
  		}catch(Exception e){
  			
  		}
  		//To get the Watchlist Audits
  		if("W".equalsIgnoreCase(auditStatus))
  			auditList = myAuditsDao.getWatchListForAudits(legalEntityCode, auditTypeCode, fromDate); 
  		
  		DataTableResponse ds=myAuditsDao.getAuditsOnDashboard(legalEntityCode,userId,search,orderColumn,
		orderDirection,page,size,auditStatus,auditTypeCode, unitsListToConcatinatedString,unitsList,fromDate,toDate, auditList);
		return ds;
	}
	
	
	@Override
	public List<RiskSummaryDtls> getRiskCntByBusinssAndProdByRiskCapId(int legalEntityCode, String auditTypeCode, String planId,String auditId, String auditStatus) {
		List<RiskSummaryDtls> ratingObscntlst= null;
		if(auditStatus != null && auditStatus.equalsIgnoreCase("AP"))
			ratingObscntlst=myAuditsDao.getRiskCntByBusinssAndProdByMapping(legalEntityCode,auditTypeCode,planId,auditId,auditStatus);
		else 
			ratingObscntlst=myAuditsDao.getRiskCntByBusinssAndProdByRiskId(legalEntityCode,auditTypeCode,planId,auditId,auditStatus); 
		
		return ratingObscntlst;
	}
	
	@Override
	public void createRiskSummary(List<RiskSummaryDtls> riskSummaryDtlsLst) {
		
		logger.info(" riskSummaryDtlsLst .."+ riskSummaryDtlsLst);
		try {
			for (RiskSummaryDtls riskSummaryDtls : riskSummaryDtlsLst) {
				riskSummaryDtls.setBusinessdateTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(riskSummaryDtls.getLegalEntityCode()));
				riskSummaryDtls.setSysdateTimestamp(new Timestamp(System.currentTimeMillis()));
				riskSummaryDtls.setMakerTimestamp(riskSummaryDtls.getBusinessdateTimestamp());
				riskSummaryDtls.setEntityStatus("A");
				riskSummaryDtls.setStatus("A");
				
				myAuditsDao.flushSession();
				myAuditsDao.save(riskSummaryDtls);
			}
		}catch(Exception e) {
			e.printStackTrace(System.out);
		}
	}
	
	@Override
	public boolean isPreviousAuditExist(int legalEntityCode,String unitId,String auditTypeCode,String auditId) {
		return myAuditsDao.isPreviousAuditExist(legalEntityCode,unitId,auditTypeCode,auditId);
	}
	
	
	@Override
	public List<RiskSummaryDtls> getObservationCntByAgAsgActByAuditIdOrType(int legalEntityCode, String auditTypeCode, String planId,String auditId, String auditStatus) {
		List<RiskSummaryDtls> ratingObscntlst= null;
		if(auditStatus != null && auditStatus.equalsIgnoreCase("AP"))
			ratingObscntlst=myAuditsDao.getObservationCntByAgAsgActByMapping(legalEntityCode,auditTypeCode,planId,auditId,auditStatus);
		else 
			ratingObscntlst=myAuditsDao.getObservationCntByAgAsgActByAuditId(legalEntityCode,auditTypeCode,planId,auditId,auditStatus); 
		
		return ratingObscntlst;
	}
	
	@Override
	public List<RiskSummaryDtls> getObservationCntByAgAsgActByAuditIdOrTypeRespRvw(int legalEntityCode, String auditTypeCode, String planId,String auditId, String auditStatus, String process) {
		List<RiskSummaryDtls> ratingObscntlst= null;
		if("R".equalsIgnoreCase(process))
			ratingObscntlst=myAuditsDao.getObservationCntByAgAsgActByAuditIdResponse(legalEntityCode,auditTypeCode,planId,auditId,auditStatus);
		else if("W".equalsIgnoreCase(process))
			ratingObscntlst=myAuditsDao.getObservationCntByAgAsgActByAuditIdReview(legalEntityCode,auditTypeCode,planId,auditId,auditStatus); 
		else
			ratingObscntlst=myAuditsDao.getObservationCntByAgAsgActByAuditId(legalEntityCode,auditTypeCode,planId,auditId,auditStatus);
		return ratingObscntlst;
	}
	
	@Override
	public List<RiskSummaryDtls> getObservationCntByAuditIdReview(int legalEntityCode, String auditTypeCode, String planId,String auditId, String auditStatus) {
		List<RiskSummaryDtls> obsCntlst= null;
		obsCntlst=myAuditsDao.getObservationCntByAuditIdReview(legalEntityCode,auditTypeCode,planId,auditId,auditStatus);
		return obsCntlst;
	}
	
	@Override
	public void updateReportStatus(AuditSchedule auditSchedule) {
		myAuditsDao.updateReportStatus(auditSchedule);
	}
	
	@Override
	public String updateReportStatus(AuditDto auditDto) {
		String updateReportStatus= myAuditsDao.updateReportStatus(auditDto);
		if(auditDto != null && "RF".equalsIgnoreCase(auditDto.getReportStatus())) {
			auditObservationDao.updateAuditObservationRecordStatus(auditDto.getLegalEntityCode(), auditDto.getAuditTypeCode(), 
					auditDto.getPlanId(), auditDto.getAuditId(), "AS");
		}
		
		if(BankAuditConstant.REPORT_STATUS_IR_DISPATCH.equalsIgnoreCase(auditDto.getReportStatus())){
			//Add Grading Data to letter work table
			AuditLetterUserInputsWrk adtLtrWrk = new AuditLetterUserInputsWrk();	
			adtLtrWrk.setLegalEntityCode(auditDto.getLegalEntityCode());
			adtLtrWrk.setAuditTypeCode(auditDto.getAuditTypeCode());
			adtLtrWrk.setAuditId(auditDto.getAuditId());
			adtLtrWrk.setPlanId(auditDto.getPlanId());
			adtLtrWrk.setUnitId(auditDto.getUnitId());
			adtLtrWrk.setLetterCode(BankAuditConstant.LETTER_CODE_IR_GRADING);
			adtLtrWrk.setStatus(BankAuditConstant.GRADING_STATUS_PLANNED);
			adtLtrWrk.setMaker("NA");
			adtLtrWrk.setSysdateTimestamp(new Timestamp(System.currentTimeMillis()));
			adtLtrWrk.setBusinessdateTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(adtLtrWrk.getLegalEntityCode()));
			adtLtrWrk.setMakerTimestamp(adtLtrWrk.getBusinessdateTimestamp());
			lettersDao.save(adtLtrWrk);
		}
		
		//Mail sending/trigger
		logger.info("Before Email sending ReviewReady/Dispatch audit type .."+ auditDto.getAuditTypeCode());
		try {
			if(BankAuditConstant.EMAIL_INSPECTION && !"BRANCHI".equalsIgnoreCase(auditDto.getAuditTypeCode())) { // BRANCHI audit type Email trigger suppressed.
				String inspRptStatus=auditDto.getReportStatus();
				logger.info("Before sending Email in updateReportStatus / Review Inspection ..");
				logger.info("auditId .. "+auditDto.getAuditId() +" reportStatus .. "+ auditDto.getReportStatus()+" :: "+inspRptStatus);
				
				//if("RRR".equalsIgnoreCase( auditDto.getReportStatus())) {  // Call on click of Ready for Review by PIO.  // Changed from RAR to RRR
				//	emailService.sendReadyForReview(auditDto.getLegalEntityCode(), auditDto.getAuditId());
				//}else 
				
				if("RRR".equalsIgnoreCase(inspRptStatus)) {  		// When clicked by PIO, for Review
					emailService.sendEmailDuringInpsectionReview(auditDto.getLegalEntityCode(), auditDto.getAuditId(), inspRptStatus);
				}else if("RAR".equalsIgnoreCase(inspRptStatus)) { // When Allocator allocates to Reviewer
					emailService.sendEmailDuringInpsectionReview(auditDto.getLegalEntityCode(), auditDto.getAuditId(), inspRptStatus);
				}else if("RC".equalsIgnoreCase( inspRptStatus)) {  // When Reviewer completes Review
					emailService.sendEmailDuringInpsectionReview(auditDto.getLegalEntityCode(), auditDto.getAuditId(), inspRptStatus);
				}else if("FS".equalsIgnoreCase( inspRptStatus)) {  // When PIO re-submit for review
					emailService.sendEmailDuringInpsectionReview(auditDto.getLegalEntityCode(), auditDto.getAuditId(), inspRptStatus);
				}else if("RA".equalsIgnoreCase( inspRptStatus)) {  // When Reviewer accepted Review
					emailService.sendEmailDuringInpsectionReview(auditDto.getLegalEntityCode(), auditDto.getAuditId(), inspRptStatus);
				}else if("RS".equalsIgnoreCase( inspRptStatus)) {  // When Reviewer finalized inspection
					emailService.sendEmailDuringInpsectionReview(auditDto.getLegalEntityCode(), auditDto.getAuditId(), inspRptStatus);
				}else if("RD".equalsIgnoreCase( inspRptStatus)) {
					emailService.sendInspectionDispatch(auditDto.getLegalEntityCode(), auditDto.getAuditId());
				}
			}
		}catch(Exception e){
			e.printStackTrace(System.out);
		}//Mail trigger, End here
		
		return updateReportStatus;
	}
	
	@Override
	public AuditSchedule getAuditDetailsByPlanIdAndAuditId(int legalEntityCode, String auditTypeCode, String planId,
			String auditId) {
		AuditSchedule auditDtls=myAuditsDao.getAuditDetailsByPlanIdAndAuditId(legalEntityCode,auditTypeCode,planId,auditId); 
		 return auditDtls; 
	}
	
	@Override
	public void updateMyAuditRatingParameterStatus(AuditSchedule auditSchedule) {
		logger.info("Inside updateMyAuditRatingParameterStatus .. "+ auditSchedule.getAuditId()+" :: "+auditSchedule.getLegalEntityCode()+" :: "+auditSchedule.getRatingParameterStatus());
		myAuditsDao.updateMyAuditRatingParameterStatus(auditSchedule); // Updating the AuditSchedule
		
		String ratingParameterStatus=auditSchedule.getRatingParameterStatus();
		try {
			/********** Update Audit Rating *********/
			// Updating when status is "RPP=>Rating Pending Auth"-> Submitted by PIO ||  "RPRU=> Rating Interim Reviewed"-> Saved by Reviewer ||  "RPR=>Rating Reviewed"-> Submitted by Reviewer ||  "RPS=>Rating Submitted"-> Submitted by HO Reviewer 
			//if("RPP".equalsIgnoreCase(ratingParameterStatus) || "RPR".equalsIgnoreCase(ratingParameterStatus) || "RPS".equalsIgnoreCase(ratingParameterStatus)) {
			if("RPP".equalsIgnoreCase(ratingParameterStatus) || "RPR".equalsIgnoreCase(ratingParameterStatus) || "RPS".equalsIgnoreCase(ratingParameterStatus)  || "RPRU".equalsIgnoreCase(ratingParameterStatus) ) { // RPRU also included, as during Interim review/Save by Reviewer the Rating score to update
				if("RPR".equalsIgnoreCase(ratingParameterStatus) || "RPP".equalsIgnoreCase(ratingParameterStatus)){
					auditRatingParameterScoreDao.updateAuditRatingParamEffectiveScores(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId(), auditSchedule.getRatingParameterStatus());
				}
				myAuditsDao.updateAuditRatingStatus(auditSchedule, ratingParameterStatus);  // Updating the AuditRating				
			}
			if("RPR".equalsIgnoreCase(ratingParameterStatus) || "RPS".equalsIgnoreCase(ratingParameterStatus) ){					
				AuditScheduleStagesStatusHst auditScheduleStagesStatusHst = new AuditScheduleStagesStatusHst();					 
				auditScheduleStagesStatusHst.setCode(ratingParameterStatus);
				auditScheduleStagesStatusHst.setStagesStatus(ratingParameterStatus);
				auditScheduleStagesStatusHst.setActionType(BankAuditConstant.ACTION_TYPE_SUPERVISORY_RATING);
				auditScheduleStagesStatusHstService.saveAuditStagesStatus(auditSchedule, auditScheduleStagesStatusHst);
			}else{					
				Map<String, Object> auditSchStagesStatusHstProperties = new HashMap<String, Object>();
				auditSchStagesStatusHstProperties.put("legalEntityCode", auditSchedule.getLegalEntityCode());
				auditSchStagesStatusHstProperties.put("auditTypeCode", auditSchedule.getAuditTypeCode());
				auditSchStagesStatusHstProperties.put("auditId", auditSchedule.getAuditId());
				auditSchStagesStatusHstProperties.put("actionType", BankAuditConstant.ACTION_TYPE_SUPERVISORY_RATING);
				auditSchStagesStatusHstProperties.put("code", ratingParameterStatus);			
				auditSchStagesStatusHstProperties.put("stagesStatus", ratingParameterStatus);					
				auditSchStagesStatusHstProperties.put("makerId",  auditSchedule.getActionMakerId());
				
				AuditScheduleStagesStatusHst auditScheduleStagesStatusHst = new AuditScheduleStagesStatusHst();	
				if(!BankAuditUtil.isEmptyString(auditSchedule.getAssigneeId())){
					auditSchStagesStatusHstProperties.put("assigneeId", auditSchedule.getAssigneeId());
					auditScheduleStagesStatusHst.setAssigneeRole("G12");						
				}	
				
				AuditScheduleStagesStatusHst  auditScheduleStagesStatusHstChk = 
						(AuditScheduleStagesStatusHst) myAuditsDao.getUniqueEntityByMatchingProperties(AuditScheduleStagesStatusHst.class, auditSchStagesStatusHstProperties);
				if(auditScheduleStagesStatusHstChk != null){ 
					auditScheduleStagesStatusHst.setId(auditScheduleStagesStatusHstChk.getId());
				}  									 
				auditScheduleStagesStatusHst.setCode(ratingParameterStatus);
				auditScheduleStagesStatusHst.setStagesStatus(ratingParameterStatus);
				auditScheduleStagesStatusHst.setActionType(BankAuditConstant.ACTION_TYPE_SUPERVISORY_RATING);
				auditScheduleStagesStatusHstService.saveAuditStagesStatus(auditSchedule, auditScheduleStagesStatusHst);					
			}
		}catch(Exception e) {
			e.printStackTrace(System.out);
		}
	}
	
	@Override
	public void updateMyAuditRatingComplianceObsScoreStatus(AuditSchedule auditSchedule) {
		logger.info("Inside updateMyAuditRatingComplianceObsScoreStatus .. "+ auditSchedule.getAuditId()+" :: "+auditSchedule.getLegalEntityCode()+" :: "+auditSchedule.getRatingComplianceStatus());
		myAuditsDao.updateMyAuditRatingComplianceObsScoreStatus(auditSchedule); // Updating the AuditSchedule
	 
		String ratingCompStatus =auditSchedule.getRatingComplianceStatus();
		if("RCDS".equalsIgnoreCase(ratingCompStatus) || "RCFS".equalsIgnoreCase(ratingCompStatus)){
			AuditScheduleStagesStatusHst  auditScheduleStagesStatusHst = new  AuditScheduleStagesStatusHst();
			if("RCDS".equalsIgnoreCase(ratingCompStatus)){
				auditScheduleStagesStatusHst.setCode(BankAuditConstant.RATING_DESK);
			}else{
				auditScheduleStagesStatusHst.setCode(BankAuditConstant.RATING_FIELD);
			}			
			auditScheduleStagesStatusHst.setStagesStatus(ratingCompStatus);
			auditScheduleStagesStatusHst.setActionType(BankAuditConstant.ACTION_TYPE_COMPLIANCE_RATING);
			
			auditScheduleStagesStatusHst.setAssigneeId(null);
		    auditScheduleStagesStatusHstService.saveAuditStagesStatus(auditSchedule, auditScheduleStagesStatusHst);
		}else{
			Map<String, Object> auditSchStagesStatusHstProperties = new HashMap<String, Object>();
			auditSchStagesStatusHstProperties.put("legalEntityCode", auditSchedule.getLegalEntityCode());
			auditSchStagesStatusHstProperties.put("auditTypeCode", auditSchedule.getAuditTypeCode());
			auditSchStagesStatusHstProperties.put("auditId", auditSchedule.getAuditId());
			auditSchStagesStatusHstProperties.put("actionType", BankAuditConstant.ACTION_TYPE_COMPLIANCE_RATING);
			auditSchStagesStatusHstProperties.put("code", ratingCompStatus);			
			auditSchStagesStatusHstProperties.put("stagesStatus", ratingCompStatus);					
			auditSchStagesStatusHstProperties.put("makerId",  auditSchedule.getActionMakerId());	
			
			AuditScheduleStagesStatusHst auditScheduleStagesStatusHst = new AuditScheduleStagesStatusHst();	 
			if(!BankAuditUtil.isEmptyString(auditSchedule.getAssigneeId())){
				auditSchStagesStatusHstProperties.put("assigneeId", auditSchedule.getAssigneeId()); 
				auditScheduleStagesStatusHst.setAssigneeRole("G12"); 
			}
								
			AuditScheduleStagesStatusHst  auditScheduleStagesStatusHstChk = 
					(AuditScheduleStagesStatusHst) myAuditsDao.getUniqueEntityByMatchingProperties(AuditScheduleStagesStatusHst.class, auditSchStagesStatusHstProperties);
			if(auditScheduleStagesStatusHstChk != null){ 
				auditScheduleStagesStatusHst.setId(auditScheduleStagesStatusHstChk.getId());
			}  						
			 
			if("RCDDF".equalsIgnoreCase(ratingCompStatus) || "RCDU".equalsIgnoreCase(ratingCompStatus) 
					||  "RCDM".equalsIgnoreCase(ratingCompStatus) ||  "RCDS".equalsIgnoreCase(ratingCompStatus)){
				auditScheduleStagesStatusHst.setCode(BankAuditConstant.RATING_DESK);
			}else{
				auditScheduleStagesStatusHst.setCode(BankAuditConstant.RATING_FIELD);
			} 
			auditScheduleStagesStatusHst.setStagesStatus(ratingCompStatus);
			auditScheduleStagesStatusHst.setActionType(BankAuditConstant.ACTION_TYPE_COMPLIANCE_RATING);
			auditScheduleStagesStatusHstService.saveAuditStagesStatus(auditSchedule, auditScheduleStagesStatusHst);					
		}		
	}
	
	@Override
	public void updateMyAuditRatingParameterRemarksSave(AuditSchedule auditSchedule) {
		logger.info("Inside updateMyAuditRatingParameterStatus .. "+ auditSchedule.getAuditId()+" :: "+auditSchedule.getLegalEntityCode()+" :: "+auditSchedule.getRatingParameterStatus());
		myAuditsDao.updateMyAuditRatingParameterStatus(auditSchedule); // Updating the AuditSchedule
		
		String ratingParameterStatus=auditSchedule.getRatingParameterStatus();
		try {
			/********** Update Reviews from PIO->RO and RO->HO *********/
			// Updating when status is "RPP=> RO_Remarks=PIO_Remarks" && "RPR=> RO_Remarks=RO_Remarks  
			if("RPRU".equalsIgnoreCase(ratingParameterStatus) || "RPHU".equalsIgnoreCase(ratingParameterStatus)) {
				auditRatingParameterScoreDao.updateAuditRatingParamRemarks(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId(), auditSchedule.getRatingParameterStatus());
			}
		}catch(Exception e) {
			e.printStackTrace(System.out);
		}
	}
	
	/*This method can be enhanced in future for more params to add*/
	@Override
	public AuditSchedule getAuditByAuditId(int legalEntityCode, String auditTypeCode, String planId, String auditId) {
		AuditSchedule auditDtls=myAuditsDao.getAuditByAuditId(legalEntityCode,auditTypeCode,planId,auditId); 
		 return auditDtls; 
	}
	
	@Override
	public EntityAuditDataDto getEntityAuditData(int legalEntityCode, String auditTypeCode, String auditId, String unitId) {
		EntityAuditDataDto entityDataDtls=myAuditsDao.getEntityAuditData(legalEntityCode,auditTypeCode,auditId,unitId); 
		return entityDataDtls; 
	}
	
	@Override
	public 	List<AuditSchedule> getAuditSchedules(Integer legalEntityCode, String auditTypeCode){
		return myAuditsDao.getAuditSchedules(legalEntityCode, auditTypeCode);
	}
	
	@Override
	public List<AuditActionItem> getAuditActionItem(Integer legalEntityCode, String auditTypeCode, String auditId){
		return myAuditsDao.getAuditActionItem(legalEntityCode, auditTypeCode, auditId);
	}
	
	@Override
	public AuditSchedule checkLatestITISAuditDetailsForUnit(Integer legalEntityCode, String unitId){
		logger.info(" Inside checkLatestITISAuditDetailsForUnit .."+legalEntityCode  +" :: "+unitId);		 
		AuditSchedule auditSchedule = myAuditsDao.checkLatestITISAuditDetailsForUnit(legalEntityCode, unitId);
		if(auditSchedule != null){
			Date actualStartDate = auditSchedule.getActualStartDate();			
			Map<String, LocalDate> financialYearMap = BankAuditUtil.getFinancialYearDates(actualStartDate);
			LocalDate financialYearStartDt  = financialYearMap.get("FIN_YR_START_DATE");
			LocalDate financialYearEndDt = financialYearMap.get("FIN_YR_END_DATE");			
			auditSchedule.setLastAuditFinancialYearITIS(financialYearStartDt.getYear()+"-"+((financialYearEndDt.getYear()+"").substring(2, 4)));
		}
		return auditSchedule;
	}
	
	@Override
	public String getFinancialYearByAuditId(Integer legalEntityCode, String auditTypeCode, String auditId) {
		return myAuditsDao.getFinancialYearByAuditId(legalEntityCode, auditTypeCode, auditId);
	}

	@Override
	public void updateAuditStatusDetailAfterInitiate(Integer legalEntityCode, String auditTypeCode, String planId, String auditId, Integer totalObservations){				
		logger.info(" Inside updateAuditStatusDetailOnInitiate .."+legalEntityCode+" :: "+auditTypeCode  +" :: "+auditId);
		 
		Map<String, Object> properties = new HashMap<String, Object>();
		properties.put("legalEntityCode", legalEntityCode);
		properties.put("auditTypeCode", auditTypeCode);
		properties.put("auditId", auditId);
		properties.put("planId", planId);
		AuditSchedule auditSchedule = (AuditSchedule) auditObservationDao.getUniqueEntityByMatchingProperties(AuditSchedule.class, properties);	
		
		properties.put("userType", "L");
		AuditTeam auditTeam = (AuditTeam) auditObservationDao.getUniqueEntityByMatchingProperties(AuditTeam.class, properties);	
 				 
		AuditRating auditRating = new AuditRating();
		auditRating.setLegalEntityCode(auditSchedule.getLegalEntityCode());
		auditRating.setAuditTypeCode(auditSchedule.getAuditTypeCode());
		auditRating.setAuditId(auditSchedule.getAuditId());		
		auditRating.setMaker(auditTeam.getUserId());
		auditRating.setMakerTimestamp(new Timestamp(System.currentTimeMillis()));
		auditRating.setEntityStatus(BankAuditConstant.STATUS_UNAUTH);
		auditRating.setStatus(BankAuditConstant.STATUS_UNAUTH);
		auditRating.setUnitId(auditSchedule.getUnitId());
		
		AuditScheduleStatus auditScheduleStatus = new AuditScheduleStatus();		
		auditScheduleStatus.setLegalEntityCode(auditSchedule.getLegalEntityCode());
		auditScheduleStatus.setAuditTypeCode(auditSchedule.getAuditTypeCode());
		auditScheduleStatus.setAuditId(auditSchedule.getAuditId()); 	
		auditScheduleStatus.setUnitId(auditSchedule.getUnitId());
		auditScheduleStatus.setTotalObservations(totalObservations);
		 		 
		myAuditsDao.save(auditRating);
		myAuditsDao.save(auditScheduleStatus);
		myAuditsDao.flushSession();				
	}
	
	private void updateAuditStatusDetailOnFinalize(AuditSchedule auditSchedule){				
		logger.info(" Inside updateAuditStatusDetailOnFinalize .."+auditSchedule.getAuditId()  +" :: "+auditSchedule.getUnitId());
	 
		Map<String, Object> properties = new HashMap<String, Object>();
		properties.put("legalEntityCode", auditSchedule.getLegalEntityCode());
		properties.put("auditTypeCode", auditSchedule.getAuditTypeCode());
		properties.put("auditId", auditSchedule.getAuditId());
		AuditScheduleStatus auditScheduleStatus = (AuditScheduleStatus) auditObservationDao.getUniqueEntityByMatchingProperties(AuditScheduleStatus.class, properties);		
 		
		List<Object[]> statusCountList =  auditObservationDao.getObservationsCountByStatusAttributesOnSubmit(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), 
				auditSchedule.getAuditId(), true, false, false);
		
		logger.info("auditScheduleStatus .. "+auditScheduleStatus);
		if(statusCountList != null && statusCountList.size()>0){
			Object[] countsArr = statusCountList.get(0);
			logger.info("countsArr .. "+countsArr);
			if(auditScheduleStatus!=null && countsArr!=null) {
				if(countsArr[1]!=null)auditScheduleStatus.setNonComplianceObservations(Integer.parseInt(countsArr[1].toString()));
				if(countsArr[2]!=null)auditScheduleStatus.setNonComplianceMajorObservations(Integer.parseInt(countsArr[2].toString()));
				if(countsArr[3]!=null)auditScheduleStatus.setNonComplianceMinorObservations(Integer.parseInt(countsArr[3].toString()));
				if(countsArr[4]!=null)auditScheduleStatus.setNonCompliancePersistenceObservations(Integer.parseInt(countsArr[4].toString()));
				if(countsArr[5]!=null)auditScheduleStatus.setComplianceObservations(Integer.parseInt(countsArr[5].toString()));
				if(countsArr[6]!=null)auditScheduleStatus.setNaObservationsExcludeOthers(Integer.parseInt(countsArr[6].toString()));	
				if(countsArr[7]!=null)auditScheduleStatus.setNaObservationsIncludeOthers(Integer.parseInt(countsArr[7].toString()));			
				auditScheduleStatus.setPendingWithBank(auditScheduleStatus.getNonComplianceObservations());
			}
		}
		if(auditScheduleStatus!=null )
			myAuditsDao.update(auditScheduleStatus); 				
	}

}
