package com.bankaudit.rest.process.service;

import java.time.LocalDate;
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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.bankaudit.constants.BankAuditConstant;
import com.bankaudit.dto.DataTableResponse;
import com.bankaudit.process.model.AuditSchedule;
import com.bankaudit.process.model.AuditScheduleStagesStatusHst;
import com.bankaudit.process.model.AuditScheduleStatus;
import com.bankaudit.rest.process.dao.AuditObservationDao;
import com.bankaudit.rest.process.dao.AuditRatingComplianceScoreDao;
import com.bankaudit.rest.process.dao.AuditReviewDao;
import com.bankaudit.util.BankAuditUtil;

@Service
@Transactional("transactionManager")
public class AuditReviewServiceImpl implements AuditReviewService {
	
	@Autowired(required=true)
	AuditReviewDao auditReviewDao;
	
	@Autowired(required=true)
	AuditObservationDao auditObservationDao;
		
	@Autowired
	EmailService emailService;
	
	@Autowired
	AuditScheduleStagesStatusHstService auditScheduleStagesStatusHstService;
	
	static final Logger logger = Logger.getLogger(AuditReviewServiceImpl.class);

	@Override
	public DataTableResponse getMyReviewList(int legalEntityCode, 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 = auditReviewDao.getMyReviewList(legalEntityCode, userId, search, orderColumn, orderDirection, page, size,
				financialYear, auditTypeCode, financialYearStrtEndList);
		return ds;
	}
	
	@Override
	public AuditSchedule getReviewAuditByPlanIdAndAuditId(int legalEntityCode, String auditTypeCode, String planId,
			String auditId) {
		AuditSchedule auditDtls=auditReviewDao.getReviewAuditByPlanIdAndAuditId(legalEntityCode,auditTypeCode,planId,auditId); 
		 return auditDtls; 
	}
	
	@Autowired(required=true)
	AuditRatingComplianceScoreDao auditRatingComplianceScoreDao;
	
	@Override
	public void updateAuditReviewStatus(AuditSchedule auditSchedule) {
		try {
			String reviewStatus= auditSchedule.getReviewStatus();
			logger.info("updateAuditReviewStatus reviewStatus .."+reviewStatus);
			auditReviewDao.updateAuditReviewStatus(auditSchedule);
			
			//BaaSDOS Specific
			if(auditSchedule != null && "WI".equalsIgnoreCase(auditSchedule.getReviewStatus())) {
				auditObservationDao.updateAuditObservationRecordStatus(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), 
						auditSchedule.getPlanId(), auditSchedule.getAuditId(), "WI");				
				//insert data into observation compliance score table
				boolean isDataPresent= auditRatingComplianceScoreDao.verifyDataPresentForComplianceObsScore(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId());
				if(!isDataPresent){
					auditRatingComplianceScoreDao.createAndGetAuditRatingComplianceScore(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId(), 
						 auditSchedule.getAuditTypeCode(),  auditSchedule.getUnitId(), auditSchedule.getReviewerId());					
				}				
			}else if(auditSchedule != null && "WS".equalsIgnoreCase(auditSchedule.getReviewStatus())) {
				auditObservationDao.updateAuditObservationRecordStatus(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), 
						auditSchedule.getPlanId(), auditSchedule.getAuditId(), "WS");				
			}	
			saveUpdateAuditStatusDetailOnScrutinyAction(auditSchedule, auditSchedule.getReviewStatus());		
			auditObservationDao.flushSession();
			
			//Mail sending/trigger
			try {
			if(BankAuditConstant.EMAIL_INSPECTION) {
				logger.info("Before sending Email in updateAuditReviewStatus .."+ auditSchedule.getAuditId());
				logger.info("AuditStatus .. "+auditSchedule.getAuditStatus()+" ObsStatus .. "+auditSchedule.getObservationStatus() +" reportStatus .. "+auditSchedule.getReportStatus());
				logger.info("RespondStatus .. "+auditSchedule.getRespondStatus() +" ReviewStatus .. "+ auditSchedule.getReviewStatus() );
				if(auditSchedule != null && "WI".equalsIgnoreCase(auditSchedule.getReviewStatus())) {  // Mail trigger when Review Initiate and assigned to a Scrutini
					emailService.sendScurityAssigned(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId());
				}else if(auditSchedule != null && "WS".equalsIgnoreCase(auditSchedule.getReviewStatus())) {
					emailService.sendFurtherCompliance(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId());
				}
			}
			}catch(Exception e){
				e.printStackTrace(System.out);
			}//Mail trigger, End here
			
			/*if("WS".equalsIgnoreCase(reviewStatus)) {
				String str1=auditReviewDao.updateProbSevirtyScoreRiskwise(auditSchedule);
				String str2=auditReviewDao.updateResidualriskAssessmentwiseCallHealthIndex(auditSchedule);
			}*/
		}catch(Exception e) {
			e.printStackTrace(System.out);
		}
	}
	
	@Override
	public void updateAuditClosureStatus(AuditSchedule auditSchedule) {
		try {
			String auditStatus= auditSchedule.getAuditStatus();
			logger.info("updateAuditClosureStatus AuditStatus .."+auditStatus);
			auditReviewDao.updateAuditClosureStatus(auditSchedule);
			auditObservationDao.updateComplianceScrutinyRemarkStatus(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(),
					auditSchedule.getPlanId(), auditSchedule.getAuditId(), BankAuditConstant.STATUS_AUTH);  
			
			saveUpdateAuditStatusDetailOnScrutinyAction(auditSchedule, BankAuditConstant.AUDIT_STATUS_AC);
			auditObservationDao.flushSession();
		}catch(Exception e) {
			e.printStackTrace(System.out);
		}
	}
	@Override
	public String isReviewObsPendingBfrReviewSubmit(AuditSchedule auditSchedule) {
		String isReviewObsPendingBfrReviewSubmit=auditReviewDao.isReviewObsPendingBfrReviewSubmit(auditSchedule); 
		 return isReviewObsPendingBfrReviewSubmit; 
	}
	
	@Override
	public DataTableResponse getReviewObservationList(int legalEntityCode,String planId,String auditId, String search, Integer orderColumn,
			String orderDirection, Integer page, Integer size) {
		DataTableResponse ds=auditReviewDao.getReviewObservationList(legalEntityCode,planId,auditId,search,orderColumn,
				orderDirection,page,size);
		return ds;
	}
	
	@Override
	public String isRatingsGiven(int legalEntityCode,String auditId) {
		return auditReviewDao.isRatingsGiven(legalEntityCode, auditId); 
		   
	}
	
	@Override
	public void updateAuditReviewerId(AuditSchedule auditSchedule) {
		try { 
			logger.info("updateAuditReviewerId AuditStatus .."+auditSchedule.getAuditStatus());
			auditReviewDao.updateAuditReviewerId(auditSchedule);			
			
			saveUpdateAuditStatusDetailOnScrutinyAction(auditSchedule, "ModifyReviewer");
			auditObservationDao.flushSession();
			
			//Mail sending/trigger
			try {
			if(BankAuditConstant.EMAIL_INSPECTION) {
				logger.info("Before sending Email in updateAuditReviewerId .."+ auditSchedule.getAuditId()+ "AuditStatus .."+auditSchedule.getAuditStatus());
				logger.info("RespondStatus .. "+auditSchedule.getRespondStatus() +" ReviewStatus .. "+ auditSchedule.getReviewStatus() );
				if(auditSchedule != null && "WI".equalsIgnoreCase(auditSchedule.getReviewStatus())) {  // Mail trigger when assigned to another Scrutinizer
					emailService.sendScurityAssigned(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId());
				}
			}
			}catch(Exception e){
				e.printStackTrace(System.out);
			}//Mail trigger, End here
			
		}catch(Exception e) {
			e.printStackTrace(System.out);
		}
	}
	
	@Override
	public void deleteDeskComplianceDataFromWrkTmp(int legalEntityCode,String auditTypeCode, String planId,String auditId){
		auditReviewDao.deleteDeskComplianceDataFromWrkTmp(legalEntityCode, auditTypeCode, planId, auditId);
	} 
	
	private void saveUpdateAuditStatusDetailOnScrutinyAction(AuditSchedule auditSchedule, String status){
		logger.info(" Inside saveUpdateAuditStatusDetailOnScrutinyAction .. "+ status);
		if(BankAuditConstant.STATUS_SCRUTINY_SUBMITTED.equalsIgnoreCase(status)){
			List<Object[]> statusCountList = auditObservationDao.getObservationsCountByStatusAttributesOnSubmit(auditSchedule.getLegalEntityCode(),  auditSchedule.getAuditTypeCode(), auditSchedule.getAuditId(),
					false, false, true);
			if(statusCountList != null && statusCountList.size() > 0){
				
				Object[] statusCount = statusCountList.get(0);
				
				Map<String, Object> properties = new HashMap<>();
				properties.put("legalEntityCode", auditSchedule.getLegalEntityCode());				
				properties.put("auditTypeCode", auditSchedule.getAuditTypeCode());		
				properties.put("auditId", auditSchedule.getAuditId());	
				
				AuditScheduleStatus auditScheduleStatus = (AuditScheduleStatus) auditObservationDao.getUniqueEntityByMatchingProperties(AuditScheduleStatus.class, properties);
				 
				auditScheduleStatus.setFurtherComplianceOnScrutinySubmit(Integer.parseInt(statusCount[1].toString()));
				auditScheduleStatus.setCarryForwardOnScrutinySubmit(Integer.parseInt(statusCount[2].toString()));
				auditScheduleStatus.setAcceptedOnScrutinySubmit(Integer.parseInt(statusCount[3].toString()));
				
				auditScheduleStatus.setPendingWithScrutiniser(0);
				auditScheduleStatus.setPendingWithBank(auditScheduleStatus.getFurtherComplianceOnScrutinySubmit());
				auditScheduleStatus.setScrutinyAcceptedAsOn(auditScheduleStatus.getAcceptedOnScrutinySubmit());
				auditScheduleStatus.setScrutinyCarryForwardAsOn(auditScheduleStatus.getCarryForwardOnScrutinySubmit());
				auditScheduleStatus.setScrutinyfurtherComplianceAsOn(auditScheduleStatus.getFurtherComplianceOnScrutinySubmit());
				
				auditObservationDao.flushSession();
				auditObservationDao.update(auditScheduleStatus); 
			}
			
			AuditScheduleStagesStatusHst auditScheduleStagesStatusHstData = new AuditScheduleStagesStatusHst();		
			auditScheduleStagesStatusHstData.setActionType(BankAuditConstant.ACTION_TYPE_SCRUTINY);
			auditScheduleStagesStatusHstData.setCode(BankAuditConstant.REVIEW_STATUS_WS);
			auditScheduleStagesStatusHstData.setStagesStatus(BankAuditConstant.REVIEW_STATUS_WS);
			
			auditScheduleStagesStatusHstData.setAssigneeId(null);
			auditScheduleStagesStatusHstService.saveAuditStagesStatus(auditSchedule, auditScheduleStagesStatusHstData);
			
		}else if(BankAuditConstant.STATUS_SCRUTINY_INITIATED.equalsIgnoreCase(status)){
			AuditScheduleStagesStatusHst auditScheduleStagesStatusHst = new AuditScheduleStagesStatusHst(); 
			auditScheduleStagesStatusHst.setActionType(BankAuditConstant.ACTION_TYPE_SCRUTINY);
			auditScheduleStagesStatusHst.setCode(BankAuditConstant.REVIEW_STATUS_WI);
			auditScheduleStagesStatusHst.setStagesStatus(BankAuditConstant.REVIEW_STATUS_WI); 
			auditScheduleStagesStatusHst.setAssigneeRole("G4");
			auditScheduleStagesStatusHstService.saveAuditStagesStatus(auditSchedule, auditScheduleStagesStatusHst); 
		}else if("ModifyReviewer".equalsIgnoreCase(status)){
			AuditScheduleStagesStatusHst auditScheduleStagesStatusHstData = new AuditScheduleStagesStatusHst();		
			auditScheduleStagesStatusHstData.setActionType(BankAuditConstant.ACTION_TYPE_SCRUTINY);
			auditScheduleStagesStatusHstData.setCode(BankAuditConstant.REVIEWER_MODIFIED);
			auditScheduleStagesStatusHstData.setStagesStatus(BankAuditConstant.REVIEWER_MODIFIED); 
			auditScheduleStagesStatusHstData.setAssigneeRole("G4");	
			auditScheduleStagesStatusHstData.setUnitId(auditSchedule.getUnitId()!=null?auditSchedule.getUnitId().split("-")[0]:"");					
			auditScheduleStagesStatusHstService.saveAuditStagesStatus(auditSchedule, auditScheduleStagesStatusHstData);
		}else if(BankAuditConstant.AUDIT_STATUS_AC.equalsIgnoreCase(status)){
			AuditScheduleStagesStatusHst auditScheduleStagesStatusHstData = new AuditScheduleStagesStatusHst();		
			auditScheduleStagesStatusHstData.setActionType(BankAuditConstant.ACTION_TYPE_SCRUTINY);
			auditScheduleStagesStatusHstData.setCode(BankAuditConstant.AUDIT_STATUS_AC);
			auditScheduleStagesStatusHstData.setStagesStatus(BankAuditConstant.AUDIT_STATUS_AC);
			auditScheduleStagesStatusHstData.setAssigneeId(null);
			auditScheduleStagesStatusHstService.saveAuditStagesStatus(auditSchedule, auditScheduleStagesStatusHstData);
		}	
		
	}
	
}
