package com.bankaudit.rest.process.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.jboss.logging.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
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 org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.bankaudit.constants.BankAuditConstant;
import com.bankaudit.dto.DataTableResponse;
import com.bankaudit.dto.process.AuditRatingDto;
import com.bankaudit.process.model.AuditSchedule;
import com.bankaudit.process.model.AuditScheduleWrkTmp;
import com.bankaudit.rest.process.service.AuditRatingService;
import com.bankaudit.service.BusinessDateService;
import com.bankaudit.util.BankAuditUtil;
import com.bankaudit.util.ServiceStatus;



@RestController

@RequestMapping("/api/auditRating")
public class AuditRatingController {
	
	@Autowired
	AuditRatingService auditRatingService;
	
	@Autowired
	BusinessDateService businessDateService;
	
	static final Logger logger = Logger.getLogger(AuditRatingController.class);
	
	
	
@RequestMapping(value = "/getAll", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
	DataTableResponse getAuditSchedules(
			@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,
			@RequestParam("userId")String userId,
			@RequestParam("role") String role,
			@RequestParam(value="unitCode",required=false) String unitCode,
			@RequestParam(value="documentType")String documentType,	 
			@RequestParam(value="documentSubType")String documentSubType,
			@RequestParam(required = false, value = "financialYear") @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate financialYear,
			@RequestParam(required = false, value = "auditTypeCode") String auditTypeCode){

		DataTableResponse dataTableResponse = null;

		if (!BankAuditUtil.isEmptyString(drawStr) && !BankAuditUtil.isEmptyString(length)
				&& !BankAuditUtil.isEmptyString(start)) {
			try {
				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);
				}
				logger.info("getAll legalEntityCode:: "+legalEntityCodeStr +" userId:: "+ userId +" role:: "+role+" finYear ::"+financialYear+" auditType ::"+auditTypeCode);
				dataTableResponse = auditRatingService.getAuditRatingList(Integer.parseInt(legalEntityCodeStr),userId, unitCode,  role, search, orderColumn, orderDirection, 
						page, size, documentType, documentSubType, financialYear, auditTypeCode);
				logger.info("Inside controller dataTableResponse .... "+dataTableResponse);
				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;
	}
	
	
@RequestMapping(value="/getByPlanIdAndAuditIdAndStatus/{legalEntityCode}/{auditTypeCode}/{planId}/{auditId}/{ratingStatus}/{role}",method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus getByPlanIdAndAuditIdAndStatus(
			@PathVariable("legalEntityCode") Integer legalEntityCode,
			@PathVariable("auditTypeCode") String auditTypeCode,
			@PathVariable("planId") String planId,
			@PathVariable("auditId")String auditId,
			//@PathVariable("status")String status
			@PathVariable("ratingStatus")String status,
			@PathVariable("role")String role
			){
		ServiceStatus serviceStatus=new ServiceStatus();
		if(legalEntityCode!=null
				&& !BankAuditUtil.isEmptyString(auditTypeCode) && !BankAuditUtil.isEmptyString(planId) && !BankAuditUtil.isEmptyString(auditId)){
			try {
				AuditRatingDto auditDtl=auditRatingService.getAuditByPlanIdAndAuditIdAndStatus(legalEntityCode,auditTypeCode,planId,auditId,status,role); 
				if(auditDtl!=null){
					serviceStatus.setResult(auditDtl);
					serviceStatus.setStatus("success");
					serviceStatus.setMessage("successfuly retrieved ");
				}else {
					serviceStatus.setStatus("failure");
					serviceStatus.setMessage("ids not found");
				}
			} catch (Exception e) {
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
				e.printStackTrace();
			}
		}else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("invalid parameter");
		}
				return serviceStatus;
	}
	
	
@RequestMapping(value = "/updateAuditScheduleComplianceRating", method=RequestMethod.PUT,consumes=MediaType.APPLICATION_JSON_VALUE,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus updateAuditScheduleComplianceRating(@RequestBody  AuditRatingDto auditRatingDto){
		ServiceStatus serviceStatus=new ServiceStatus();
		AuditSchedule  auditScheduleWrkTmp = auditRatingDto.getAuditSchedule();
		if(auditScheduleWrkTmp!=null
				&&  !BankAuditUtil.isEmptyString(auditScheduleWrkTmp.getLegalEntityCode()+"")
				&&  !BankAuditUtil.isEmptyString(auditScheduleWrkTmp.getAuditId())
				&&  !BankAuditUtil.isEmptyString(auditScheduleWrkTmp.getAuditTypeCode())
				&&  !BankAuditUtil.isEmptyString(auditScheduleWrkTmp.getPlanId())
				&&  !BankAuditUtil.isEmptyString(auditRatingDto.getAuditId()) ){
			try {
				 
				String status = auditRatingService.updateAuditScheduleComplianceRating(auditRatingDto);
				if(status.equals(BankAuditConstant.SUCCESS)){
					serviceStatus.setStatus("success");
					serviceStatus.setMessage("successsfully updated");
				}else{
					serviceStatus.setStatus("failed");
					serviceStatus.setMessage("failed");
				}
				
			} catch (Exception e) {
				logger.error(e.getStackTrace());
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
			}
		}else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("at least one observation is required ");
		}
		
		return serviceStatus; 
	}
	
	//Upload Rating Documents
	
@RequestMapping(value="/uploadDocuments" ,method=RequestMethod.POST,consumes=MediaType.MULTIPART_FORM_DATA_VALUE,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus uploadDocuments(
		@RequestParam(value="maker")String maker,
		@RequestParam(value="role")String role,
		@RequestParam(value="files")CommonsMultipartFile[] files,
		@RequestParam(value="legalEntityCode")Integer legalEntityCode,
		@RequestParam(value="auditTypeCode")String auditTypeCode,		
		@RequestParam("planId") String planId,
		@RequestParam("auditId")String auditId,
		@RequestParam(value="documentName", required=false)String documentName,
		@RequestParam(value="documentType")String documentType,				
		@RequestParam(value="warningCheck")String warningCheck,
		@RequestParam(value="documentSubType")String documentSubType){
	
			ServiceStatus serviceStatus=new ServiceStatus();
			Map<String, Object> result=new HashMap<>();
			try {
				if(legalEntityCode !=null   && auditTypeCode !=null && files!=null ){ 
					if(BankAuditUtil.isEmptyString(documentName)){
						documentName="Compliance Rating";
					}
					Boolean isWarning=false;
					String duplicateFileNames="";
					List<Integer> duplicateDocIds=new ArrayList<>(); 
					for (CommonsMultipartFile commonsMultipartFile : files) {
						if(!BankAuditUtil.validateFileType(commonsMultipartFile, BankAuditConstant.DOC_TYPES)){
							serviceStatus.setStatus("failure");
							serviceStatus.setMessage("file type : "+BankAuditUtil.getFileExtension(commonsMultipartFile.getOriginalFilename())
							+" not supported");
							return serviceStatus;
						} 
					}
					if(isWarning){
						serviceStatus.setStatus("warning");
					    serviceStatus.setMessage("file " + duplicateFileNames + "  already exist do you want to replace  ");
					    serviceStatus.setResult(duplicateDocIds);
					    return serviceStatus;
					} 
					  Map<String, Integer> uploadStatus = auditRatingService.uploadDocuments(legalEntityCode, auditTypeCode, auditId, planId, 
							  	documentType,  documentName, maker, role, files, documentSubType);
					  result.put("documentUploadIds", uploadStatus);
					  
					serviceStatus.setResult(result);
					serviceStatus.setStatus("success");
					serviceStatus.setMessage("successfully uploaded");
					
				}else {
					serviceStatus.setStatus("failure");
					serviceStatus.setMessage("Invalid payload");
				}
				
			} catch (Exception e) {
				logger.error(e.getStackTrace());
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
			}
			return serviceStatus;
	}
	

	
@RequestMapping(value="/deleteAuditRatingDocuments" ,method=RequestMethod.DELETE,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus  deleteAuditRatingDocuments(				  
		@RequestParam(value="legalEntityCode") Integer legalEntityCode, 
		@RequestParam(value="id") Integer id, 
		@RequestParam(value="auditTypeCode") String auditTypeCode,
		@RequestParam("planId") String planId,
		@RequestParam("auditId")String auditId,
		@RequestParam(value="documentType")String documentType,				
		@RequestParam(value="status") String status,
		//@RequestParam(value="ratingStatus") String ratingStatus,		
		@RequestParam(value="entityStatus") String entityStatus,
		@RequestParam(value="documentSubType", required=false)String documentSubType)  {
			ServiceStatus serviceStatus=new ServiceStatus();
			
			if(!BankAuditUtil.isEmptyString(auditTypeCode) && !BankAuditUtil.isEmptyString(status) 
					&& id!=null && id>0
					&& legalEntityCode!=null && legalEntityCode>0){
				try{
				   String updateStatus = auditRatingService.deleteAuditRatingDocumentsFromUI(legalEntityCode, id, auditTypeCode, auditId, planId, status,
						   entityStatus, documentType, documentSubType);
					if(updateStatus.equals(BankAuditConstant.SUCCESS)){
						serviceStatus.setStatus("success");
						serviceStatus.setMessage("successfully deleted the selected document");
					}else{
						serviceStatus.setStatus("failure");
						serviceStatus.setMessage("failed to delete the selected document");
					}
				}catch (Exception e) {
					logger.error(e.getStackTrace());
					serviceStatus.setStatus("failure");
					serviceStatus.setMessage("failure");
				}
			}else{
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("missing parameter value document id");
			} 			
			
			return serviceStatus;
	}
	
@RequestMapping(value="/deleteAllAuditRatingDocuments" ,method=RequestMethod.DELETE, produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus deleteAllAuditRatingDocuments(
		@RequestParam(value="legalEntityCode")Integer legalEntityCode,
		@RequestParam(value="auditTypeCode")String auditTypeCode, 
		@RequestParam("planId") String planId,
		@RequestParam("auditId")String auditId,
		@RequestParam(value="documentType")String documentType,		
		//@RequestParam(value="status") String status
		@RequestParam(value="ratingStatus") String status,
		@RequestParam(value="documentSubType")String documentSubType
		){
	
			ServiceStatus serviceStatus=new ServiceStatus();
			
			try {
				
				String updateStatus = auditRatingService.deleteAllAuditRatingDocumentsFromUI(legalEntityCode, auditTypeCode, auditId, planId, status, documentType, documentSubType);
				
				if(updateStatus.equals(BankAuditConstant.SUCCESS)){
					serviceStatus.setStatus("success");
					serviceStatus.setMessage("successfully deleted all the documents");
				}else{
					serviceStatus.setStatus("failure");
					serviceStatus.setMessage("failed to delete  documents");
				}
				
			} catch (Exception e) {
				logger.error(e.getStackTrace());
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
			}
			return serviceStatus;
	}
	
	/*
@RequestMapping(value="/downloadRatingDocument",method = RequestMethod.GET)
    public void  downloadRatingDocument(
    		@RequestParam(value="id",required=true)Integer id,
    		@RequestParam(value="legalEntityCode",required=true)Integer legalEntityCode,
    		//@RequestParam(value="status",required=true)String status,
    		@RequestParam(value="ratingStatus") String status,		
    		@RequestParam(value="documentType",required=true)String documentType,    		
    		@RequestParam(value="userId",required=true)String userId,
    		@RequestParam(value="userRoleId",required=true)String userRoleId,
    		@RequestParam(value="documentSubType")String documentSubType,
    		HttpServletRequest request,
            HttpServletResponse response) throws IOException {    	
    	
    	ServletContext context=request.getServletContext();
    	String filePath =auditRatingService.getReferencePathById(legalEntityCode, id, status);
    	 	if(!BankAuditUtil.isEmptyString(filePath)){
		    		File file=new File(filePath);
		    		if(file.isFile()){
		    			
		    			 int BUFFER_SIZE = 4096;
		    			 FileInputStream inputStream = new FileInputStream(file);

		    			 String mimeType = context.getMimeType(filePath); // get MIME type of the file
		                 
		                 if (mimeType == null) {
		                     mimeType = "application/octet-stream"; // set to binary type if MIME mapping not found
		                 }
		              
		                 // set content attributes for the response
		                 response.setContentType(mimeType);
		                 response.setContentLength((int) file.length());
		          
		                 // set headers for the response
		                 String headerKey = "Content-Disposition";
		                 String headerValue = String.format("attachment; filename=\"%s\"",file.getName());
		                 response.setHeader(headerKey, headerValue);
		          
		                 // get output stream of the response
		                 OutputStream outStream = response.getOutputStream();
		          
		                 byte[] buffer = new byte[BUFFER_SIZE];
		                 int bytesRead = -1;
		          
		                 // write bytes read from the input stream into the output stream
		                 while ((bytesRead = inputStream.read(buffer)) != -1) {
		                     outStream.write(buffer, 0, bytesRead);
		                 }
		                 inputStream.close();
		                 outStream.close();                  
		        	}else {
		    			 response.getWriter().print("Document not exist");
					}
		    }else {
   			 response.getWriter().print("Document not exist");
			}
   	}*/
	
	
	/*
@RequestMapping(value="/getDocumentDetails" ,method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus getDocumentDetails(
			@RequestParam(value="legalEntityCode") Integer legalEntityCode, 
			//@RequestParam(value="status") String status,	
			@RequestParam(value="ratingStatus") String status,		
			@RequestParam(value="auditTypeCode") String auditTypeCode, 
			@RequestParam("planId") String planId,
			@RequestParam("auditId")String auditId,
			@RequestParam(required=false,value="documentType") String documentType,			
			@RequestParam(required=false,value="userId") String userId,
			@RequestParam(required=false,value="userRoleId") String userRoleId,
			@RequestParam(value="documentSubType", required=false)String documentSubType){
		ServiceStatus serviceStatus=new ServiceStatus();
		try {  
			 List<Object> auditRatingDocuments = auditRatingService.getAuditRatingDocumentDetails(legalEntityCode, auditTypeCode, auditId, 
					planId, documentType, userId, userRoleId, status,   documentSubType);
			if((auditRatingDocuments!=null && !auditRatingDocuments.isEmpty()) ){
				serviceStatus.setResult(auditRatingDocuments);
				serviceStatus.setStatus("success");
				serviceStatus.setMessage("successfully got the result ");
			} 
			else {
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("No docs found ");
			}
		} catch (Exception e) {
			logger.error(e.getStackTrace());
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("failure");
		}
		return serviceStatus;
	}*/
	
	
@RequestMapping(value="/getOnsiteComplianceStatus/{legalEntityCode}/{auditTypeCode}/{planId}/{auditId}",method=RequestMethod.GET,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus getOnsiteComplianceStatus(
			@PathVariable("legalEntityCode") Integer legalEntityCode,
			@PathVariable("auditTypeCode") String auditTypeCode,
			@PathVariable("planId") String planId,
			@PathVariable("auditId")String auditId 
			){
		ServiceStatus serviceStatus=new ServiceStatus();
		if(legalEntityCode!=null
				&& !BankAuditUtil.isEmptyString(auditTypeCode) && !BankAuditUtil.isEmptyString(planId) && !BankAuditUtil.isEmptyString(auditId)){
			try {
				String onsiteComplianceStatus=auditRatingService.getOnsiteComplianceStatus(legalEntityCode,auditTypeCode,planId,auditId); 
				if(onsiteComplianceStatus!=null && onsiteComplianceStatus.equalsIgnoreCase(BankAuditConstant.SUCCESS)){ 
					serviceStatus.setStatus("success");
					serviceStatus.setMessage("on-site rating has been given");
				}else if(BankAuditConstant.VALIDATION_FAILED.equalsIgnoreCase(onsiteComplianceStatus)){
					serviceStatus.setStatus("modified");
					serviceStatus.setMessage("The modified rating awaiting approval, you want to proceed with overriding with the current Approved rating?");
				}else {
					serviceStatus.setStatus("failure");
					//serviceStatus.setMessage("please provide the onsite compliance score and rating");
					serviceStatus.setMessage("Compliance rating should be authorised before finalising the IR.");
				}
			} catch (Exception e) {
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
				e.printStackTrace();
			}
		}else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("invalid parameter");
		}
		return serviceStatus;
	}
	
	
@RequestMapping(value="/deleteOnsiteComplianceDataFromWrkTmp/{legalEntityCode}/{auditTypeCode}/{planId}/{auditId}",method=RequestMethod.DELETE,produces=MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus deleteOnsiteComplianceDataFromWrkTmp(
			@PathVariable("legalEntityCode") Integer legalEntityCode,
			@PathVariable("auditTypeCode") String auditTypeCode,
			@PathVariable("planId") String planId,
			@PathVariable("auditId")String auditId 
			){
		ServiceStatus serviceStatus=new ServiceStatus();
		if(legalEntityCode!=null
				&& !BankAuditUtil.isEmptyString(auditTypeCode) && !BankAuditUtil.isEmptyString(planId) && !BankAuditUtil.isEmptyString(auditId)){
			try {
				 	auditRatingService.deleteOnsiteComplianceDataFromWrkTmp(legalEntityCode,auditTypeCode,planId,auditId); 				 
					serviceStatus.setStatus("success");
					serviceStatus.setMessage("successfully deleted the modified record");
				 
			}catch (Exception e) {
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
				e.printStackTrace();
			}
		}else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("invalid parameter");
		}
		return serviceStatus;
	}
	
}
