package com.bankaudit.rest.process.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
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.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.process.model.AuditAdhocDocument;
import com.bankaudit.process.model.AuditAdhocReport;
import com.bankaudit.rest.process.service.AuditAdhocReportService;
import com.bankaudit.util.BankAuditUtil;
import com.bankaudit.util.ServiceStatus;



@RestController

@RequestMapping("/api/auditAdhocReport")
public class AuditAdhocReportController {

	@Autowired
	AuditAdhocReportService auditAdhocReportService;

	 private static final int BUFFER_SIZE = 4096; 
	 
	static final Logger logger = Logger.getLogger(AuditAdhocReportController.class);

	
@RequestMapping(value = "/uploadDocument", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus uploadDocument(@RequestParam(value = "legalEntityCode") String legalEntityCodeStr,
			@RequestParam(value = "auditTypeCode") String auditTypeCode, @RequestParam(value = "planId") String planId,
			@RequestParam(value = "auditId") String auditId, @RequestParam(value = "reportedBy") String reportedBy,
			@RequestParam(value = "files") CommonsMultipartFile[] files) {

		Integer legalEntityCode = null;
		if (!BankAuditUtil.isEmptyString(legalEntityCodeStr)) {
			legalEntityCode = Integer.parseInt(legalEntityCodeStr);
		}

		ServiceStatus serviceStatus = new ServiceStatus();
		Map<String, Object> result = new HashMap<>();
		try {
			if (files != null) {
				List<AuditAdhocDocument> auditAdhocDocuments = auditAdhocReportService
						.getAuditAdhocDocument(legalEntityCode, auditTypeCode, planId, auditId, reportedBy);

				Boolean isWarning = false;

				String duplicateFileNames = "";

				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 (auditAdhocDocuments != null) {
						String existingPath = "";
						for (AuditAdhocDocument auditAdhocDocument : auditAdhocDocuments) {
							existingPath = auditAdhocDocument.getReferencePath();
							existingPath = existingPath.substring(existingPath.lastIndexOf("/") + 1);
							existingPath = existingPath.substring(existingPath.indexOf("_")+1);
							if (existingPath.equalsIgnoreCase(commonsMultipartFile.getOriginalFilename())) {

								isWarning = true;
								duplicateFileNames = duplicateFileNames + " "
										+ commonsMultipartFile.getOriginalFilename();

							}

						}

					}

				}

				if (isWarning) {
					serviceStatus.setStatus("warning");
					serviceStatus.setMessage(
							"file " + duplicateFileNames + "  already exist , please delete before update ");
					return serviceStatus;
				}

				// result.put("documentUploadId",);

				serviceStatus.setResult(auditAdhocReportService.uploadDocument(legalEntityCode, auditTypeCode, planId,
						auditId, reportedBy, files));
				serviceStatus.setStatus("success");
				serviceStatus.setMessage("successfully uploaded");
			} else {
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("Invalid payload");
			}

		} catch (Exception e) {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("failure");
		}
		return serviceStatus;
	}

	
@RequestMapping(value = "/deleteDocumentById/{legalEntityCode}/{id}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus deleteauditAdhocDocument(@PathVariable("id") Integer id,
			@PathVariable("legalEntityCode") Integer legalEntityCode) {

		ServiceStatus serviceStatus = new ServiceStatus();

		if (id != null && legalEntityCode != null) {

			try {
				auditAdhocReportService.deleteauditAdhocDocument(id, legalEntityCode);

				serviceStatus.setStatus("success");
				serviceStatus.setMessage("successfully deleted");

			} catch (Exception e) {

				e.printStackTrace();
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");

			}
		} else {

			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("Invalid payload");
		}

		return serviceStatus;
	}

	/*
	 * 
@RequestMapping(method = RequestMethod.POST, consumes =
	 * MediaType.APPLICATION_JSON_VALUE, produces =
	 * MediaType.APPLICATION_JSON_VALUE) ServiceStatus
	 * createAuditAdhocReport(@RequestBody List<AuditAdhocReport>
	 * auditAdhocReports) { ServiceStatus serviceStatus = new ServiceStatus();
	 * 
	 * if (auditAdhocReports != null && !auditAdhocReports.isEmpty()) { try {
	 * 
	 * auditAdhocReportService.createAuditAdhocReport(auditAdhocReports);
	 * serviceStatus.setStatus("success");
	 * serviceStatus.setMessage("successsfully saved"); } catch (Exception e) {
	 * 
	 * serviceStatus.setStatus("failure"); serviceStatus.setMessage("failure");
	 * logger.error(e.getStackTrace()); } } else {
	 * serviceStatus.setStatus("failure");
	 * serviceStatus.setMessage("at least one AuditAdhocReport is required "); }
	 * 
	 * return serviceStatus; }
	 */

	
@RequestMapping(method = RequestMethod.PUT, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus updateAuditAdhocReport(@RequestBody List<AuditAdhocReport> auditAdhocReports) {
		ServiceStatus serviceStatus = new ServiceStatus();

		if (auditAdhocReports != null && !auditAdhocReports.isEmpty()) {
			try {

				auditAdhocReportService.updateAuditAdhocReport(auditAdhocReports);
				serviceStatus.setStatus("success");
				serviceStatus.setMessage("successsfully saved");
			} catch (Exception e) {

				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");
				logger.error(e.getStackTrace());
				e.printStackTrace();
			}
		} else {
			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("at least one AuditAdhocReport is required ");
		}

		return serviceStatus;
	}

	
@RequestMapping(value = "/getAuditAdhocDocuments", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus getAuditAdhocDocuments(@RequestParam(value = "legalEntityCode") String legalEntityCodeStr,
			@RequestParam(value = "auditTypeCode") String auditTypeCode, @RequestParam(value = "planId") String planId,
			@RequestParam(value = "auditId") String auditId, @RequestParam(value = "reportedBy") String reportedBy) {
		ServiceStatus serviceStatus = new ServiceStatus();

		if (!BankAuditUtil.isEmptyString(legalEntityCodeStr) && !BankAuditUtil.isEmptyString(auditTypeCode)
				&& !BankAuditUtil.isEmptyString(planId) && !BankAuditUtil.isEmptyString(auditId)
				&& !BankAuditUtil.isEmptyString(reportedBy)) {

			try {
				List<AuditAdhocDocument> auditAdhocDocuments = auditAdhocReportService.getAuditAdhocDocument(
						Integer.parseInt(legalEntityCodeStr), auditTypeCode, planId, auditId, reportedBy);

				if (auditAdhocDocuments != null && !auditAdhocDocuments.isEmpty()) {
					serviceStatus.setResult(auditAdhocDocuments);
					serviceStatus.setStatus("success");
					serviceStatus.setMessage("successfully retrieved");
				} else {
					serviceStatus.setStatus("failure");
					serviceStatus.setMessage("no documents found ");
				}

			} catch (Exception e) {

				e.printStackTrace();
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");

			}
		} else {

			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("Invalid payload");
		}

		return serviceStatus;
	}

	
@RequestMapping(value = "/getAuditAdhocReportsReportedBy", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus getAuditAdhocReports(@RequestParam(value = "legalEntityCode") String legalEntityCodeStr,
			@RequestParam(value = "auditTypeCode") String auditTypeCode, @RequestParam(value = "planId") String planId,
			@RequestParam(value = "auditId") String auditId, @RequestParam(value = "reportedBy") String reportedBy) {
		ServiceStatus serviceStatus = new ServiceStatus();

		if (!BankAuditUtil.isEmptyString(legalEntityCodeStr) && !BankAuditUtil.isEmptyString(auditTypeCode)
				&& !BankAuditUtil.isEmptyString(planId) && !BankAuditUtil.isEmptyString(auditId)
				&& !BankAuditUtil.isEmptyString(reportedBy)) {

			try {
				List<AuditAdhocReport> auditAdhocReports = auditAdhocReportService.getAuditAdhocReports(
						Integer.parseInt(legalEntityCodeStr), auditTypeCode, planId, auditId, reportedBy);

				if (auditAdhocReports != null && !auditAdhocReports.isEmpty()) {
					serviceStatus.setResult(auditAdhocReports);
					serviceStatus.setStatus("success");
					serviceStatus.setMessage("successfully retrieved");
				} else {
					serviceStatus.setStatus("failure");
					serviceStatus.setMessage("no documents found ");
				}

			} catch (Exception e) {

				e.printStackTrace();
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");

			}
		} else {

			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("Invalid payload");
		}

		return serviceStatus;
	}

	
@RequestMapping(value = "/getAuditAdhocReportsTargetUser", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
	ServiceStatus getAuditAdhocReportsTargetUser(@RequestParam(value = "legalEntityCode") String legalEntityCodeStr,
			@RequestParam(value = "auditTypeCode") String auditTypeCode, @RequestParam(value = "planId") String planId,
			@RequestParam(value = "auditId") String auditId, @RequestParam(value = "targetUser") String targetUser) {
		ServiceStatus serviceStatus = new ServiceStatus();

		if (!BankAuditUtil.isEmptyString(legalEntityCodeStr) && !BankAuditUtil.isEmptyString(auditTypeCode)
				&& !BankAuditUtil.isEmptyString(planId) && !BankAuditUtil.isEmptyString(auditId)
				&& !BankAuditUtil.isEmptyString(targetUser)) {

			try {
				List<AuditAdhocReport> auditAdhocReports = auditAdhocReportService.getAuditAdhocReportsTargetUser(
						Integer.parseInt(legalEntityCodeStr), auditTypeCode, planId, auditId, targetUser);

				if (auditAdhocReports != null && !auditAdhocReports.isEmpty()) {
					serviceStatus.setResult(auditAdhocReports);
					serviceStatus.setStatus("success");
					serviceStatus.setMessage("successfully retrieved");
				} else {
					serviceStatus.setStatus("failure");
					serviceStatus.setMessage("no documents found ");
				}

			} catch (Exception e) {

				e.printStackTrace();
				serviceStatus.setStatus("failure");
				serviceStatus.setMessage("failure");

			}
		} else {

			serviceStatus.setStatus("failure");
			serviceStatus.setMessage("Invalid payload");
		}

		return serviceStatus;
	}

	
@RequestMapping(value = "/downloadDocumentById", method = RequestMethod.GET)
	public void downloadAuditAdhocDocument(@RequestParam(value = "id", required = true) Integer id,
			HttpServletRequest request, HttpServletResponse response) throws IOException {

		ServletContext context = request.getServletContext();

		AuditAdhocDocument auditAdhocDocument =auditAdhocReportService.getAuditAdhocDocumentById(id) ;

		if (auditAdhocDocument != null 
				&& !auditAdhocDocument.getStatus().equals("D")) {

			String filePath = auditAdhocDocument.getReferencePath();
			if (!BankAuditUtil.isEmptyString(filePath)) {
				File file = new File(filePath);
				if (file.isFile()) {
					FileInputStream inputStream = new FileInputStream(file);
					// get MIME type of the file
					String mimeType = context.getMimeType(filePath);
					if (mimeType == null) {
						// set to binary type if MIME mapping not found
						mimeType = "application/octet-stream";
					}
					// 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("inline; filename=\"%s\"", file.getName());
					String headerValue = String.format("attachment; filename=\"%s\"", file.getName()); // to download all the files, instead of opening on the browser.
					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");
		}

	}

}
