package com.bankaudit.rest.process.service;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.BeanUtils;
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.AuditLetterUserInputs;
import com.bankaudit.process.model.AuditLetterUserInputsHst;
import com.bankaudit.process.model.AuditLetterUserInputsWrk;
import com.bankaudit.process.model.AuditSchedule;
import com.bankaudit.process.model.AuditScheduleHst;
import com.bankaudit.process.model.AuditScheduleWrk;
import com.bankaudit.process.model.AuditTeam;
import com.bankaudit.process.model.AuditTeamWrk;
import com.bankaudit.rest.process.dao.AuditPlanUpdateDao;
import com.bankaudit.rest.process.dao.MyAuditsDao;
import com.bankaudit.service.BusinessDateService;
import com.bankaudit.service.MaintEntityService;
import com.bankaudit.util.BankAuditUtil;

@Service("auditPlanUpdateService")
@Transactional("transactionManager")
public class AuditPlanUpdateServiceImpl implements AuditPlanUpdateService {

	@Autowired
	AuditPlanUpdateDao auditPlanUpdateDao;
	
	@Autowired
	MyAuditsDao myAuditsDao;
	
	@Autowired
	MaintEntityService maintEntityService;
	
	@Autowired
	BusinessDateService businessDateService;
	
	@Autowired
	AuditScheduleService auditScheduleService;
	
	@Override
	public void createAuditTeamWrk(AuditTeamWrk auditTeamWrk) {
		auditPlanUpdateDao.save(auditTeamWrk);
	}
	
	@Override
	public DataTableResponse getAuditPlanUpdateList(int legalEntityCode, String userId, String search, Integer orderColumn,
			String orderDirection, Integer page, Integer size, LocalDate financialYear, String auditTypeCode ) {
		List<String> unitsList=maintEntityService.getSubBranchesGyUserIdOrUnitId(legalEntityCode,"user", userId);
		List<LocalDate>  financialYearStrtEndList=null;
		if(financialYear!=null) financialYearStrtEndList= BankAuditUtil.getFinancialStartEndDatesNxtFrom(financialYear);
		return auditPlanUpdateDao.getAuditsList(legalEntityCode,userId,search,orderColumn,	orderDirection,page,size, unitsList,
				financialYear, auditTypeCode, financialYearStrtEndList);
	}
	
	@Override
	public AuditSchedule getAuditByPlanIdAndAuditId(int legalEntityCode, String auditTypeCode, String planId,
			String auditId, String teamStatus) {
		AuditSchedule auditSchedule = null;
		if(teamStatus.equals(BankAuditConstant.STATUS_AUTH))
			auditSchedule= auditPlanUpdateDao.getAuditByPlanIdAndAuditId(legalEntityCode,auditTypeCode,planId,auditId);
		else
			auditSchedule = auditPlanUpdateDao.getAuditScheduleWrkByPlanIdAndAuditId(legalEntityCode,auditTypeCode,planId,auditId);
		
		auditPlanUpdateDao.flushSession();
		List<AuditTeam> list = getAuditTeamsByAuditId(legalEntityCode, auditTypeCode, planId, auditId,teamStatus);
		String teamMember ="";
		for(AuditTeam at : list) {
			if(at.getUserType().equals("L")) {
				auditSchedule.setTeamLead(at.getUserId());
			}else {
				teamMember = teamMember + at.getUserId()+",";
			}
		}
		if(teamMember.contains(","))
			auditSchedule.setTeamMember(teamMember.substring(0,teamMember.lastIndexOf(",")));
		return auditSchedule;
	}
	
	@Override
	public List<AuditTeam> getAuditTeamsByAuditId(int legalEntityCode,String auditTypeCode, String planId,String auditId, String teamStatus){
		return auditPlanUpdateDao.getAuditTeamsByAuditId(legalEntityCode, auditTypeCode, planId, auditId, teamStatus);
	}
	
	@Override
	public void updateAuditTeams(AuditSchedule auditSchedule) {
		if(!auditSchedule.getTeamStatus().equalsIgnoreCase(BankAuditConstant.STATUS_AUTH)){
			if(auditSchedule.getTeamStatus().equalsIgnoreCase(BankAuditConstant.STATUS_UNAUTH)
					|| auditSchedule.getTeamStatus().equalsIgnoreCase(BankAuditConstant.STATUS_MOD)){
				auditSchedule.setTeamMakerTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(auditSchedule.getLegalEntityCode()));
			}
			auditPlanUpdateDao.deleteAuditTeam(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId(), BankAuditConstant.STATUS_UNAUTH);
			if (auditSchedule.getAuditTeams()!=null){
				for (AuditTeam auditTeam : auditSchedule.getAuditTeams()) {
					AuditTeamWrk auditTeamWrk = new AuditTeamWrk();
					BeanUtils.copyProperties(auditTeam, auditTeamWrk);
					auditPlanUpdateDao.flushSession();
					auditPlanUpdateDao.saveOrUpdate(auditTeamWrk);
				}
			}
		}else{
			auditPlanUpdateDao.deleteAuditTeam(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId(), BankAuditConstant.STATUS_AUTH);
			if (auditSchedule.getAuditTeams()!=null){
				for (AuditTeam auditTeam : auditSchedule.getAuditTeams()) {
					auditPlanUpdateDao.flushSession();
					auditPlanUpdateDao.saveOrUpdate(auditTeam);
				}
			}
			auditPlanUpdateDao.deleteAuditTeam(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditId(), BankAuditConstant.STATUS_UNAUTH);
		}
	}

	@Override
	public List<AuditSchedule> getAuditScheduleUpdateList(int legalEntityCode, String userId, String search, Integer orderColumn,
			String orderDirection, Integer page, Integer size) {
		return auditPlanUpdateDao.getAuditScheduleUpdateList(legalEntityCode, userId, search, orderColumn, orderDirection, page, size);
	}

	@Override
	public void updateAuditSchedule(AuditSchedule auditSchedule) {
		setAuditTeams(auditSchedule);
		updateAuditTeams(auditSchedule);
		if (auditSchedule.getTeamStatus().equalsIgnoreCase(BankAuditConstant.STATUS_AUTH)) {
			AuditSchedule auditScheduledb = auditPlanUpdateDao.getAuditSchedule(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), auditSchedule.getPlanId(), auditSchedule.getAuditId());
			if (auditScheduledb != null) {
				AuditScheduleHst auditScheduleHst = new AuditScheduleHst();
				BeanUtils.copyProperties(auditScheduledb, auditScheduleHst);
				auditPlanUpdateDao.save(auditScheduleHst);
			}
			auditPlanUpdateDao.deleteAuditSchedule(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), auditSchedule.getPlanId(), auditSchedule.getAuditId());
			auditPlanUpdateDao.flushSession();
			
			// Added for Letters changes
			auditPlanUpdateDao.deleteDirectiveLetterUserInput(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), auditSchedule.getPlanId(), auditSchedule.getAuditId());
			auditPlanUpdateDao.flushSession();
			// End here
			
			auditScheduledb.setTeamCheckerTimestamp(auditSchedule.getBusinessdateTimestamp());
			//auditScheduledb.setIrFinalisationDate(auditSchedule.getIrFinalisationDate()); // non editable fields in Update Plan
			//auditScheduledb.setIrSubmissionDate(auditSchedule.getIrSubmissionDate());	// non editable fields in Update Plan
			auditScheduledb.setScheduleStartDate(auditSchedule.getScheduleStartDate());
			auditScheduledb.setScheduleEndDate(auditSchedule.getScheduleEndDate());
			auditScheduledb.setComplianceDueDate(auditSchedule.getComplianceDueDate());
			auditPlanUpdateDao.saveOrUpdate(auditScheduledb);
			
			// Added for Letters changes
			if(!BankAuditUtil.isEmptyString(auditSchedule.getUserInputStatus())){
				
				AuditLetterUserInputs auditLetterUserInputs = auditPlanUpdateDao.getAuditLetterUserInputs(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), auditSchedule.getPlanId(), auditSchedule.getAuditId());
				if (auditLetterUserInputs != null) {
					AuditLetterUserInputsHst auditLetterUserInputsHst = new AuditLetterUserInputsHst();
					BeanUtils.copyProperties(auditLetterUserInputs, auditLetterUserInputsHst);
					auditPlanUpdateDao.save(auditLetterUserInputsHst);
				} else{
					auditLetterUserInputs = new AuditLetterUserInputs();
				}
				
				auditLetterUserInputs.setLegalEntityCode(auditSchedule.getLegalEntityCode());
				auditLetterUserInputs.setAuditTypeCode(auditSchedule.getAuditTypeCode());
				auditLetterUserInputs.setAuditId(auditSchedule.getAuditId());
				auditLetterUserInputs.setPlanId(auditSchedule.getPlanId());
				auditLetterUserInputs.setLetterCode("Dr");
				auditLetterUserInputs.setUnitId(auditSchedule.getUnitId());
				auditLetterUserInputs.setMaker(auditSchedule.getUserInputMaker());
				auditLetterUserInputs.setMakerTimestamp(auditSchedule.getUserInputMakerTimeStamp());
				auditLetterUserInputs.setBusinessdateTimestamp(auditSchedule.getUserInputBusinessdateTimestamp());
				auditLetterUserInputs.setSysdateTimestamp(auditSchedule.getUserInputSysdateTimestamp());
				auditLetterUserInputs.setChecker(auditSchedule.getUserInputChecker());
				auditLetterUserInputs.setCheckerTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(auditSchedule.getLegalEntityCode()));
				auditLetterUserInputs.setAuthRejRemarks(auditSchedule.getUserInputAuthRejRemarks());			
				auditLetterUserInputs.setUserInput01(auditSchedule.getUserInput01());
				auditLetterUserInputs.setUserInput02(auditSchedule.getUserInput02());
				auditLetterUserInputs.setUserInput03(auditSchedule.getUserInput03());
				auditLetterUserInputs.setUserInput04(auditSchedule.getUserInput04());
				auditLetterUserInputs.setUserInput05(auditSchedule.getUserInput05());
				auditLetterUserInputs.setUserInput06(auditSchedule.getUserInput06());
				auditLetterUserInputs.setUserInput07(auditSchedule.getUserInput07());
				auditLetterUserInputs.setUserInput08(auditSchedule.getUserInput08());
				auditLetterUserInputs.setUserInput09(auditSchedule.getUserInput09());
				auditLetterUserInputs.setUserInput10(auditSchedule.getUserInput10());
				auditLetterUserInputs.setStatus(BankAuditConstant.STATUS_AUTH);
				auditPlanUpdateDao.flushSession();
				auditPlanUpdateDao.saveOrUpdate(auditLetterUserInputs);			
			}
			// End here, Letters
		} else {
			if (auditSchedule.getTeamStatus().equalsIgnoreCase(BankAuditConstant.STATUS_UNAUTH)
					|| auditSchedule.getTeamStatus().equalsIgnoreCase(BankAuditConstant.STATUS_MOD)) {
				auditSchedule.setTeamMakerTimestamp(
						businessDateService.getBusinessDateTimestampByLegalEntityCode(auditSchedule.getLegalEntityCode()));
			}
			AuditScheduleWrk auditScheduleWrkDb = auditPlanUpdateDao.getAuditScheduleWrk(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), auditSchedule.getPlanId(), auditSchedule.getAuditId());
			if (auditScheduleWrkDb != null) {
				auditPlanUpdateDao.flushSession();
				AuditScheduleHst auditScheduleHst = new AuditScheduleHst();
				BeanUtils.copyProperties(auditScheduleWrkDb, auditScheduleHst);
				auditPlanUpdateDao.save(auditScheduleHst);
			} else {
				AuditSchedule auditScheduleDb =auditPlanUpdateDao.getAuditSchedule(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), auditSchedule.getPlanId(), auditSchedule.getAuditId());
				auditPlanUpdateDao.flushSession();
				AuditScheduleHst auditScheduleHst = new AuditScheduleHst();
				BeanUtils.copyProperties(auditScheduleDb, auditScheduleHst);
				auditPlanUpdateDao.save(auditScheduleHst);
			}
			auditPlanUpdateDao.deleteAuditSchedule(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), auditSchedule.getPlanId(), auditSchedule.getAuditId());
			AuditScheduleWrk auditScheduleWrk = new AuditScheduleWrk();
			BeanUtils.copyProperties(auditSchedule, auditScheduleWrk);
			auditPlanUpdateDao.flushSession();
			auditPlanUpdateDao.save(auditScheduleWrk);
		
			// Added for Letters changes
			if(!BankAuditUtil.isEmptyString(auditSchedule.getUserInputStatus())){
				AuditLetterUserInputsWrk auditLetterUserInputsWrk = auditPlanUpdateDao.getAuditLetterUserInputsWrk(auditSchedule.getLegalEntityCode(), auditSchedule.getAuditTypeCode(), auditSchedule.getPlanId(), auditSchedule.getAuditId());
				if(auditLetterUserInputsWrk==null){
					auditLetterUserInputsWrk = new AuditLetterUserInputsWrk();		
					auditLetterUserInputsWrk.setBusinessdateTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(auditSchedule.getLegalEntityCode()));
					auditLetterUserInputsWrk.setSysdateTimestamp(new Date());
				} 
				
				auditLetterUserInputsWrk.setLegalEntityCode(auditSchedule.getLegalEntityCode());
				auditLetterUserInputsWrk.setAuditTypeCode(auditSchedule.getAuditTypeCode());
				auditLetterUserInputsWrk.setAuditId(auditSchedule.getAuditId());
				auditLetterUserInputsWrk.setPlanId(auditSchedule.getPlanId());
				auditLetterUserInputsWrk.setLetterCode("Dr");
				auditLetterUserInputsWrk.setUnitId(auditSchedule.getUnitId());
				auditLetterUserInputsWrk.setMaker(auditSchedule.getUserInputMaker());
				auditLetterUserInputsWrk.setMakerTimestamp(businessDateService.getBusinessDateTimestampByLegalEntityCode(auditSchedule.getLegalEntityCode()));		
				auditLetterUserInputsWrk.setUserInput01(auditSchedule.getUserInput01());
				auditLetterUserInputsWrk.setUserInput02(auditSchedule.getUserInput02());
				auditLetterUserInputsWrk.setUserInput03(auditSchedule.getUserInput03());
				auditLetterUserInputsWrk.setUserInput04(auditSchedule.getUserInput04());
				auditLetterUserInputsWrk.setUserInput05(auditSchedule.getUserInput05());
				auditLetterUserInputsWrk.setUserInput06(auditSchedule.getUserInput06());
				auditLetterUserInputsWrk.setUserInput07(auditSchedule.getUserInput07());
				auditLetterUserInputsWrk.setUserInput08(auditSchedule.getUserInput08());
				auditLetterUserInputsWrk.setUserInput09(auditSchedule.getUserInput09());
				auditLetterUserInputsWrk.setUserInput10(auditSchedule.getUserInput10());
				auditLetterUserInputsWrk.setStatus(auditSchedule.getUserInputStatus());
				auditPlanUpdateDao.flushSession();
				auditPlanUpdateDao.saveOrUpdate(auditLetterUserInputsWrk);	
			}
			// End here
		}
	}
	
	private void setAuditTeams(AuditSchedule auditSchedule) {
		List<AuditTeam> auditTeams = new ArrayList<>(); 
		AuditTeam at = new AuditTeam();
		at.setLegalEntityCode(auditSchedule.getLegalEntityCode());
		at.setAuditTypeCode(auditSchedule.getAuditTypeCode());
		at.setAuditId(auditSchedule.getAuditId());
		at.setPlanId(auditSchedule.getPlanId());
		at.setUnitId(auditSchedule.getUnitId());
		if(auditSchedule.getTeamLead() != null && !auditSchedule.getTeamLead().isEmpty()) {
			at.setUserId(auditSchedule.getTeamLead());
			at.setUserType("L");
			auditTeams.add(at);
		}
		if(auditSchedule.getTeamMember()!= null && !auditSchedule.getTeamMember().isEmpty()) {
			for(String team : auditSchedule.getTeamMember().split(",")) {
				AuditTeam atm = new AuditTeam();
				atm.setLegalEntityCode(auditSchedule.getLegalEntityCode());
				atm.setAuditTypeCode(auditSchedule.getAuditTypeCode());
				atm.setAuditId(auditSchedule.getAuditId());
				atm.setPlanId(auditSchedule.getPlanId());
				atm.setUnitId(auditSchedule.getUnitId());
				atm.setUserId(team);
				atm.setUserType("M");
				auditTeams.add(atm);
			}
		}
		auditSchedule.setAuditTeams(auditTeams);
	}

}
