package com.jasamedika.medifirst2000.controller;

import com.jasamedika.medifirst2000.constants.MessageResource;
import com.jasamedika.medifirst2000.controller.base.LocaleController;
import com.jasamedika.medifirst2000.entities.DokumenTemplate;
import com.jasamedika.medifirst2000.service.SuratMasukService;
import com.jasamedika.medifirst2000.util.StringUtil;
import com.jasamedika.medifirst2000.vo.*;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLConnection;
import java.nio.file.Files;
import java.util.List;
import java.util.Map;

import static com.jasamedika.medifirst2000.core.web.WebConstants.HttpHeaderInfo.LABEL_ERROR;
import static com.jasamedika.medifirst2000.core.web.WebConstants.HttpHeaderInfo.LABEL_SUCCESS;
import static com.jasamedika.medifirst2000.util.CommonUtil.isNotNullOrEmpty;
import static com.jasamedika.medifirst2000.util.rest.RestUtil.getJsonHttpStatus;
import static com.jasamedika.medifirst2000.util.rest.RestUtil.getJsonResponse;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.slf4j.LoggerFactory.getLogger;
import static org.springframework.http.HttpStatus.*;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

@RestController
@RequestMapping("/surat-masuk")
public class SuratMasukController extends LocaleController<SuratMasukVO> {

	private static final Logger LOGGER = getLogger(SuratMasukController.class);

	@Autowired
	private SuratMasukService service;

	@RequestMapping(value = "/save-document-template", method = POST, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> uploadTemplateSurat(@RequestBody DokumenTemplateVO dokumenTemplateVO,
			HttpServletRequest request) {
		String result = service.uploadDocumentTemplateSurat(dokumenTemplateVO);
		if (isNotNullOrEmpty(result)) {
			mapHeaderMessage.put(LABEL_SUCCESS, getMessage(MessageResource.LABEL_SUCCESS, request));
			return getJsonResponse(result, CREATED, mapHeaderMessage);
		} else {
			mapHeaderMessage.put(LABEL_ERROR, "Processing data error returns empty data");
			return getJsonHttpStatus(INTERNAL_SERVER_ERROR, mapHeaderMessage);
		}
	}

	@RequestMapping(value = "/download-dokumen-template/{id}", method = GET)
	public void downloadFileDokumenTemplate(HttpServletResponse response, @PathVariable("id") Integer id)
			throws IOException {
		DokumenTemplate result = service.findById(id);
		File file = new File(result.getFileLocation());
		if (!file.exists()) {
			String errorMessage = "Sorry. The file you are looking for does not exist";

			LOGGER.error("{} in service.findById", errorMessage);

			OutputStream outputStream = response.getOutputStream();
			outputStream.write(errorMessage.getBytes(UTF_8));
			outputStream.close();
			return;
		}
		String mimeType = URLConnection.guessContentTypeFromName(file.getName());
		if (mimeType == null) {
			LOGGER.warn("mimetype is not detectable in service.findById, will take default");

			mimeType = "application/octet-stream";
		}
		response.setContentType(mimeType);
		response.setHeader("Content-Disposition", String.format("inline; filename=\"" + result.getFileName() + "\""));
		response.setContentLength((int) file.length());
		InputStream inputStream = new BufferedInputStream(Files.newInputStream(file.toPath()));
		FileCopyUtils.copy(inputStream, response.getOutputStream());
	}

	@RequestMapping(value = "/download-dokumen/{id}", method = GET)
	public void downloadFileDokumen(HttpServletResponse response, @PathVariable("id") Integer id) throws IOException {
		Map<String, Object> result = service.findPathFileById(id);
		File file = new File(result.get("pathFile").toString());
		String fileName = result.get("namaJudulDokumen").toString() + "_"
				+ StringUtil.formatNumber(result.get("noDokumen").toString(), 10) + "."
				+ FilenameUtils.getExtension(result.get("pathFile").toString());
		if (!file.exists()) {
			String errorMessage = "Sorry. The file you are looking for does not exist";

			LOGGER.error("{} in service.findPathFileById", errorMessage);

			OutputStream outputStream = response.getOutputStream();
			outputStream.write(errorMessage.getBytes(UTF_8));
			outputStream.close();
			return;
		}
		String mimeType = URLConnection.guessContentTypeFromName(file.getName());
		if (mimeType == null) {
			LOGGER.warn("mimetype is not detectable in service.findPathFileById, will take default");

			mimeType = "application/octet-stream";
		}
		response.setContentType(mimeType);
		response.setHeader("Content-Disposition", String.format("inline; filename=\"" + fileName + "\""));
		response.setContentLength((int) file.length());
		InputStream inputStream = new BufferedInputStream(Files.newInputStream(file.toPath()));
		FileCopyUtils.copy(inputStream, response.getOutputStream());
	}

	@RequestMapping(value = "/get-running-number/", method = GET)
	public String getRunningNumber(HttpServletResponse response) {
		return service.getRunningNumber();
	}

	@RequestMapping(value = "/daftar-dokumen-template", method = GET, produces = APPLICATION_JSON_VALUE)
	public List<DokumenTemplate> getAllDokumenTemplate(
			@RequestParam(value = "page", required = false, defaultValue = "0") Integer page,
			@RequestParam(value = "limit", required = false, defaultValue = "50") Integer limit,
			@RequestParam(value = "sort", required = false, defaultValue = "namaSurat") String sort,
			@RequestParam(value = "dir", required = false, defaultValue = "asc") String dir,
			@RequestParam(value = "dateStart", required = false) String dateStart,
			@RequestParam(value = "dateEnd", required = false) String dateEnd,
			@RequestParam(value = "id", required = false) Integer suratId) {
		return service.getAllDokumenTemplate(page, limit, sort, dir, dateStart, dateEnd, suratId);
	}

	@RequestMapping(value = "/save-draft-surat", method = POST, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> saveDraftSurat(@RequestBody DokumenTemplateVO dokumenTemplateVO,
			HttpServletRequest request) {
		String result = service.saveDraftSurat(dokumenTemplateVO);
		if (isNotNullOrEmpty(result)) {
			mapHeaderMessage.put(LABEL_SUCCESS, getMessage(MessageResource.LABEL_SUCCESS, request));
			return getJsonResponse(result, CREATED, mapHeaderMessage);
		} else {
			mapHeaderMessage.put(LABEL_ERROR, "Processing data error returns empty data");
			return getJsonHttpStatus(INTERNAL_SERVER_ERROR, mapHeaderMessage);
		}
	}

	@RequestMapping(value = "/get-draft-surat", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<List<Map<String, Object>>> getListDaftarDraftSuratByPeriode(
			@RequestParam(value = "dateStart") String dateStart, @RequestParam(value = "dateEnd") String dateEnd,
			@RequestParam(value = "idRuangan", required = false) Integer idRuangan) {
		List<Map<String, Object>> resultPageMap = service.getAllDraftSuratByPeriode(dateStart, dateEnd, idRuangan);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-draft-surat-by-ruangan", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<List<Map<String, Object>>> getListDaftarDraftSuratByRuanganPeriode(
			@RequestParam(value = "dateStart") String dateStart, @RequestParam(value = "idRuangan") Integer idRuangan,
			@RequestParam(value = "dateEnd") String dateEnd) {
		List<Map<String, Object>> resultPageMap = service.getAllDraftSuratByRuanganPeriode(dateStart, dateEnd,
				idRuangan);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-draft-surat-by-ruangan-pembuat", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<List<Map<String, Object>>> getListDaftarDraftSuratByRuanganPeriode(
			@RequestParam(value = "idRuangan") Integer idRuangan) {
		List<Map<String, Object>> resultPageMap = service.getAllDraftSuratByRuangan(idRuangan);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-draft-surat-by-id/{id}", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<Map<String, Object>> getListDaftarDraftById(@PathVariable("id") Integer id) {
		Map<String, Object> resultPageMap = service.getDraftSuratById(id);
		List<Map<String, Object>> ruangans = service.findByDokumenTujuanByIdDokumen(id);
		resultPageMap.put("ruangans", ruangans);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/save-kirim-draft-surat", method = POST, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> kirimDraftSurat(@RequestBody KirimDraftVO kirimDraftVO, HttpServletRequest request) {
		String result = service.saveKirimDraftSurat(kirimDraftVO);
		if (isNotNullOrEmpty(result)) {
			mapHeaderMessage.put(LABEL_SUCCESS, getMessage(MessageResource.LABEL_SUCCESS, request));
			return getJsonResponse(result, CREATED, mapHeaderMessage);
		} else {
			mapHeaderMessage.put(LABEL_ERROR, "Processing data error returns empty data");
			return getJsonHttpStatus(INTERNAL_SERVER_ERROR, mapHeaderMessage);
		}
	}

	@RequestMapping(value = "/get-draft-surat-by-id-and-ruangan/{id}/{idRuangan}", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<Map<String, Object>> getListDaftarDraftById(@PathVariable("id") Integer id,
			@PathVariable("idRuangan") Integer idRuangan) {
		Map<String, Object> resultPageMap = service.getDraftSuratByIdAndRuangan(id, idRuangan);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/save-draft-verbal-konsep", method = POST, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> saveVerbalKonsep(@RequestBody VerbalKonsepVO verbalKonsepVO,
			HttpServletRequest request) {
		String result = service.saveVerbalKonsep(verbalKonsepVO);
		if (isNotNullOrEmpty(result)) {
			mapHeaderMessage.put(LABEL_SUCCESS, getMessage(MessageResource.LABEL_SUCCESS, request));
			return getJsonResponse(result, CREATED, mapHeaderMessage);
		} else {
			mapHeaderMessage.put(LABEL_ERROR, "Processing data error returns empty data");
			return getJsonHttpStatus(INTERNAL_SERVER_ERROR, mapHeaderMessage);
		}
	}

	@RequestMapping(value = "/get-verbal-konsep-by-id-dokumen/{id}", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<Map<String, Object>> getVerbalKonsepByIdDokumen(@PathVariable("id") Integer id) {
		Map<String, Object> resultPageMap = service.getDraftSuratVerbalKonsepByIdDokumen(id);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/save-surat-masuk-dari-external", method = POST, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> saveSuratMasukDariExternal(
			@RequestBody SuratMasukDariExternalVO suratMasukDariExternalVO, HttpServletRequest request) {
		String result = service.saveSuratMasukDariExternal(suratMasukDariExternalVO);
		if (isNotNullOrEmpty(result)) {
			mapHeaderMessage.put(LABEL_SUCCESS, getMessage(MessageResource.LABEL_SUCCESS, request));
			return getJsonResponse(result, CREATED, mapHeaderMessage);
		} else {
			mapHeaderMessage.put(LABEL_ERROR, "Processing data error returns empty data");
			return getJsonHttpStatus(INTERNAL_SERVER_ERROR, mapHeaderMessage);
		}
	}

	@RequestMapping(value = "/get-surat-masuk-internal-eksternal-by-ruangan-periode/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<List<Map<String, Object>>> getListDaftarSuratMasukByRuangan(
			@RequestParam(value = "dateStart") String dateStart, @RequestParam(value = "dateEnd") String dateEnd,
			@RequestParam(value = "idRuangan", required = false) Integer idRuangan) {
		List<Map<String, Object>> resultPageMap = service.getListDokumenMasukInternalExternal(dateStart, dateEnd,
				idRuangan);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-surat-masuk-internal-eksternal-by-no-rec/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<Map<String, Object>> getSuratMasukInternalEksternalBynoRec(
			@RequestParam(value = "norec", required = false) String norec) {
		Map<String, Object> resultPageMap = service.getDokumenMasukInternalExternalBynoRec(norec);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-surat-masuk-internal-eksternal-by-id-dokumen/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<Map<String, Object>> getSuratMasukInternalEksternalByidDokumen(
			@RequestParam(value = "idDokumen", required = false) Integer idDokumen) {
		Map<String, Object> resultPageMap = service.getDokumenMasukInternalExternalByIdDokumen(idDokumen);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/save-kirim-distribusi-surat", method = POST, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> kirimDistribusiSurat(@RequestBody KirimDraftVO kirimDraftVO,
			HttpServletRequest request) {
		String result = service.saveKirimDistribusiSurat(kirimDraftVO);
		if (isNotNullOrEmpty(result)) {
			mapHeaderMessage.put(LABEL_SUCCESS, getMessage(MessageResource.LABEL_SUCCESS, request));
			return getJsonResponse(result, CREATED, mapHeaderMessage);
		} else {
			mapHeaderMessage.put(LABEL_ERROR, "Processing data error returns empty data");
			return getJsonHttpStatus(INTERNAL_SERVER_ERROR, mapHeaderMessage);
		}
	}

	@RequestMapping(value = "/save-terima-surat", method = POST, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> terimaSuratMasuk(@RequestBody KirimDraftVO kirimDraftVO, HttpServletRequest request) {
		String result = service.saveTerimaSurat(kirimDraftVO);
		if (isNotNullOrEmpty(result)) {
			mapHeaderMessage.put(LABEL_SUCCESS, getMessage(MessageResource.LABEL_SUCCESS, request));
			return getJsonResponse(result, CREATED, mapHeaderMessage);
		} else {
			mapHeaderMessage.put(LABEL_ERROR, "Processing data error returns empty data");
			return getJsonHttpStatus(INTERNAL_SERVER_ERROR, mapHeaderMessage);
		}
	}

	@RequestMapping(value = "/save-surat-masuk-to-internal-ekternal", method = POST, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> suratMasukKeInternalEksternal(
			@RequestBody SuratMasukInternalEksternalVO suratMasukInternalEksternalVO, HttpServletRequest request) {
		String result = service.saveSuratMasukKeInternalEksternal(suratMasukInternalEksternalVO);
		if (isNotNullOrEmpty(result)) {
			mapHeaderMessage.put(LABEL_SUCCESS, getMessage(MessageResource.LABEL_SUCCESS, request));
			return getJsonResponse(result, CREATED, mapHeaderMessage);
		} else {
			mapHeaderMessage.put(LABEL_ERROR, "Processing data error returns empty data");
			return getJsonHttpStatus(INTERNAL_SERVER_ERROR, mapHeaderMessage);
		}
	}

	@RequestMapping(value = "/get-surat-masuk-internal-eksternal-by-ruangan-periode-penomoran/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<List<Map<String, Object>>> getAllSuratMasukPenomoranByPeriodeAndRuangan(
			@RequestParam(value = "dateStart") String dateStart, @RequestParam(value = "dateEnd") String dateEnd,
			@RequestParam(value = "idRuangan", required = false) Integer idRuangan) {
		List<Map<String, Object>> resultPageMap = service.getAllSuratMasukPenomoranByPeriodeAndRuangan(dateStart,
				dateEnd, idRuangan);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-daftar-distribusi-surat-by-ruangan-periode/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<List<Map<String, Object>>> getListDaftarDistribusiSurat(
			@RequestParam(value = "dateStart") String dateStart, @RequestParam(value = "dateEnd") String dateEnd,
			@RequestParam(value = "idRuangan", required = false) Integer idRuangan) {
		List<Map<String, Object>> resultPageMap = service.getListDaftarDistribusiSurat(dateStart, dateEnd, idRuangan);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-surat-masuk-by-ruangan-periode-penomoran/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<List<Map<String, Object>>> getAllSuratMasukPenomoranTatausahaByPeriodeAndRuangan(
			@RequestParam(value = "dateStart") String dateStart, @RequestParam(value = "dateEnd") String dateEnd,
			@RequestParam(value = "idRuangan", required = false) Integer idRuangan) {
		List<Map<String, Object>> resultPageMap = service.getAllSuratMasukPenomoranByPeriodeAndRuanganTujuan(dateStart,
				dateEnd, idRuangan);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-surat-masuk-internal-eksternal-penomoran-by-no-rec/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<Map<String, Object>> getDokumenMasukKeluarBuatPenomoranByNoRec(
			@RequestParam(value = "norec", required = false) String norec) {
		Map<String, Object> resultPageMap = service.getDokumenMasukKeluarBuatPenomoranByNoRec(norec);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-daftar-distribusi-surat-by-ruangan-tujuan-periode/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<List<Map<String, Object>>> getListDaftarDistribusiSuratTujuan(
			@RequestParam(value = "dateStart") String dateStart, @RequestParam(value = "dateEnd") String dateEnd,
			@RequestParam(value = "idRuangan", required = false) Integer idRuangan) {
		List<Map<String, Object>> resultPageMap = service.getListDaftarDistribusiSuratTujuan(dateStart, dateEnd,
				idRuangan);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/save-surat-masuk-ke-external-penomoran", method = POST, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> saveSuratMasukKeExternalPenomoran(
			@RequestBody SuratMasukKeEksternalVO suratMasukKeEksternalVO, HttpServletRequest request) {
		String result = service.saveSuratMasukKeExternal(suratMasukKeEksternalVO);
		if (isNotNullOrEmpty(result)) {
			mapHeaderMessage.put(LABEL_SUCCESS, getMessage(MessageResource.LABEL_SUCCESS, request));
			return getJsonResponse(result, CREATED, mapHeaderMessage);
		} else {
			mapHeaderMessage.put(LABEL_ERROR, "Processing data error returns empty data");
			return getJsonHttpStatus(INTERNAL_SERVER_ERROR, mapHeaderMessage);
		}
	}

	@RequestMapping(value = "/save-surat-masuk-ke-internal-penomoran", method = POST, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> saveSuratMasukKeInternalPenomoran(
			@RequestBody SuratMasukKeInternalVO suratMasukKeInternalVO, HttpServletRequest request) {
		String result = service.saveSuratMasukKeInternal(suratMasukKeInternalVO);
		if (isNotNullOrEmpty(result)) {
			mapHeaderMessage.put(LABEL_SUCCESS, getMessage(MessageResource.LABEL_SUCCESS, request));
			return getJsonResponse(result, CREATED, mapHeaderMessage);
		} else {
			mapHeaderMessage.put(LABEL_ERROR, "Processing data error returns empty data");
			return getJsonHttpStatus(INTERNAL_SERVER_ERROR, mapHeaderMessage);
		}
	}

	@RequestMapping(value = "/get-no-surat-ke-eksternal/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> getNoSuratKeEksternal(
			@RequestParam(value = "idUnitPemrakarsa") Integer idUnitPemrakarsa,
			@RequestParam(value = "idKlasifikasiArsip") Integer idKlasifikasiArsip,
			@RequestParam(value = "idSubKlasifikasiArsip") Integer idSubKlasifikasiArsip,
			@RequestParam(value = "tahun", required = false) Integer tahun) {
		String resultPageMap = service.getNoSuratKeEksternal(idUnitPemrakarsa, idKlasifikasiArsip,
				idSubKlasifikasiArsip, tahun);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-no-surat-ke-internal/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<String> getNoSuratKeInternal(
			@RequestParam(value = "idUnitPemrakarsa") Integer idUnitPemrakarsa,
			@RequestParam(value = "bulan") Integer bulan,
			@RequestParam(value = "tahun", required = false) Integer tahun) {
		String resultPageMap = service.getNoSuratKeInternal(idUnitPemrakarsa, bulan, tahun);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-daftar-surat-masuk-ke-eksternal/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<List<Map<String, Object>>> getListSuratMasukKeEksternal(
			@RequestParam(value = "dateStart") String dateStart, @RequestParam(value = "dateEnd") String dateEnd,
			@RequestParam(value = "idRuangan", required = false) Integer idRuangan) {
		List<Map<String, Object>> resultPageMap = service.getListSuratMasukKeEksternal(dateStart, dateEnd, idRuangan);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}

	@RequestMapping(value = "/get-daftar-surat-masuk-jangka-waktu/", method = GET, produces = APPLICATION_JSON_VALUE)
	public ResponseEntity<List<Map<String, Object>>> getListSuratMasukJangkaWaktu(
			@RequestParam(value = "dateStart") String dateStart, @RequestParam(value = "dateEnd") String dateEnd,
			@RequestParam(value = "idRuangan", required = false) Integer idRuangan) {
		List<Map<String, Object>> resultPageMap = service.getListSuratMasukJangkaWaktu(dateStart, dateEnd, idRuangan);
		return getJsonResponse(resultPageMap, OK, mapHeaderMessage);
	}
}
