package com.eactive.eai.rms.onl.transaction.apim;

import com.eactive.eai.agent.command.Command;
import com.eactive.eai.agent.command.CommonCommand;
import com.eactive.eai.rms.common.base.OnlBaseAnnotationController;
import com.eactive.eai.rms.common.login.SessionManager;
import com.eactive.eai.rms.common.vo.GridResponse;
import com.eactive.eai.rms.data.entity.onl.authserver.ClientEntityService;
import com.eactive.eai.rms.data.entity.onl.eaimsg.EAIMessageUISearch;
import com.eactive.eai.rms.onl.common.exception.BizException;
import com.eactive.eai.rms.onl.manage.adapter.adapter.ui.AdapterGroupUI;
import com.eactive.eai.rms.onl.transaction.apim.ui.ApiInterfaceExportData;
import com.eactive.eai.rms.onl.transaction.apim.ui.ApiInterfaceReloadSyncSet;
import com.eactive.eai.rms.onl.transaction.apim.ui.ApiInterfaceUI;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


@Controller
public class ApiInterfaceController extends OnlBaseAnnotationController {

	public static final Log logger = LogFactory.getLog(ApiInterfaceController.class);

	private final ApiInterfaceService service;
	private final ClientEntityService clientEntityService;

	@Autowired
	public ApiInterfaceController(ApiInterfaceService service, ClientEntityService clientEntityService) {
		this.service = service;
		this.clientEntityService = clientEntityService;
	}

	@GetMapping(value = "/onl/transaction/apim/apiInterfaceMan.view")
	public void view() {
	}

	@GetMapping(value = "/onl/transaction/apim/apiInterfaceMan.view", params = "cmd=DETAIL")
	public String viewDetail() {
		return "/onl/transaction/apim/apiInterfaceManDetail";
	}

	@PostMapping(value= "/onl/transaction/apim/apiInterfaceMan.json", params = "cmd=LIST")
	public ResponseEntity<GridResponse<ApiInterfaceUI>> selectList(EAIMessageUISearch eaiMessageUISearch,
			@RequestParam(value = "sortName", required = false, defaultValue = "lastModifiedDate") String sortname,
	        @RequestParam(value = "sortOrder", required = false, defaultValue = "desc") String sortorder,
																   Pageable pageable) {
		Page<ApiInterfaceUI> page = service.selectList(eaiMessageUISearch, pageable, sortname, sortorder);
		return ResponseEntity.ok(new GridResponse<>(page));
	}

	@PostMapping(value= "/onl/transaction/apim/apiInterfaceMan.json",params = "cmd=DETAIL")
	public ResponseEntity<ApiInterfaceUI> selectDetail(String eaiSvcName) throws Exception {
		ApiInterfaceUI apiInterfaceUI = service.selectDetail(eaiSvcName);
		return ResponseEntity.ok(apiInterfaceUI);
	}

	@PostMapping(value= "/onl/transaction/apim/apiInterfaceMan.json",params = "cmd=LIST_COMBO")
	public ResponseEntity<Map<String, Object>> selectCombo(HttpServletRequest request) throws Exception {
		String userId = SessionManager.getUserId(request);
		Map<String, Object> map = service.selectCombo(userId);
		return ResponseEntity.ok(map);
	}

	@PostMapping(value= "/onl/transaction/apim/apiInterfaceMan.json",params = "cmd=LIST_DETAIL_COMBO")
	public ResponseEntity<Map<String, Object>> selectDetailCombo(HttpServletRequest request) throws Exception {
		String userId = SessionManager.getUserId(request);
		Map<String, Object> map = service.selectDetailCombo(userId);
		return ResponseEntity.ok(map);
	}

	@PostMapping(value= "/onl/transaction/apim/apiInterfaceMan.json",params = "cmd=DETAIL_ADAPTER_INFO")
	public ResponseEntity<Map<String, Object>> getHttpAdapterInfo(String adapterGroupName) throws Exception {
		Map<String, Object> map = service.getHttpAdapterInfo(adapterGroupName);
		return ResponseEntity.ok(map);
	}

	@PostMapping(value= "/onl/transaction/apim/apiInterfaceMan.json",params = "cmd=DETAIL_ADAPTER_GROUP")
	public ResponseEntity<AdapterGroupUI> selectAdapterGroupDetail(String adapterGroupName) throws Exception {
		return ResponseEntity.ok(service.selectAdapterGroupDetail(adapterGroupName));
	}

	@PostMapping(value= "/onl/transaction/apim/apiInterfaceMan.json",params = "cmd=INSERT")
	public ResponseEntity<Map<String, Object>> insert(ApiInterfaceUI apiInterfaceUI) throws Exception {
		try {
			service.insert(apiInterfaceUI);
			Map<String, Object> resultMap = null;
			resultMap = reloadSync(apiInterfaceUI);
			return ResponseEntity.ok(resultMap);
		}catch(Exception e) {
			logger.error(e);
			if(e instanceof BizException) {
				throw e;
			}
			throw new BizException("오류가 발생했습니다. 확인바랍니다. error:"+e.getMessage(), e);
		}
	}
	@PostMapping(value= "/onl/transaction/apim/apiInterfaceMan.json", params = "cmd=UPDATE")
	public ResponseEntity<Map<String, Object>> update(ApiInterfaceUI apiInterfaceUI) throws Exception {
		try {
			service.update(apiInterfaceUI);
			Map<String, Object> resultMap = null;
			resultMap = reloadSync(apiInterfaceUI);
			return ResponseEntity.ok(resultMap);
		}catch(Exception e) {
			if(e instanceof BizException) {
				throw e;
			}
			if(e instanceof DuplicateKeyException) {
				DuplicateKeyException dupEx = (DuplicateKeyException) e;
				Throwable cause = dupEx.getMostSpecificCause();
				throw new BizException("중복 오류가 발생했습니다. 확인바랍니다. 오류메시지: "+cause.getMessage());
			}
			logger.error(e);
			throw new BizException("오류가 발생했습니다. 확인바랍니다. 오류메시지: "+e.getMessage());
		}

	}
	@PostMapping(value= "/onl/transaction/apim/apiInterfaceMan.json",params = "cmd=DELETE")
	public ResponseEntity<Map<String, Object>> delete(ApiInterfaceUI apiInterfaceUI) throws Exception {
		try {

			// Get affected client IDs before deleting the API
			List<String> affectedClientIds = clientEntityService.deleteApiByEaiSvcName(apiInterfaceUI.getEaiSvcName());

			// Reload affected clients
			for (String clientId : affectedClientIds) {
				logger.info("- Reloading client [" + clientId + "]");
				agentUtilService.broadcast(new CommonCommand("com.eactive.eai.agent.authserver.ReloadClientCommand", clientId));
			}

			String standardMessageKey = service.delete(apiInterfaceUI);
			Map<String, Object> resultMap = deleteSync(standardMessageKey, apiInterfaceUI);

			return ResponseEntity.ok(resultMap);
		}catch(Exception e) {
			if(e instanceof BizException) {
				throw e;
			}
			throw new BizException("오류가 발생했습니다. 확인바랍니다. error:"+e.getMessage(), e);
		}
	}

	public Map<String, Object> reloadSync(ApiInterfaceUI apiInterfaceUI) throws Exception {
		logger.info("- 수정 동기화 시작 [" + apiInterfaceUI.getEaiSvcName() + "]");

		Command command = new CommonCommand("com.ext.eai.agent.stdmessage.ReloadSTDMessageCommand", "ALL");
		agentUtilService.broadcast(command);

		//HE01 EAI 메시지 공통부
		CommonCommand cmdHE01 = new CommonCommand("com.eactive.eai.agent.eaimessage.ReloadEAIMessageCommand", apiInterfaceUI.getEaiSvcName());
		HashMap<String, Object> resultMap = agentUtilService.broadcast(cmdHE01);
		logger.info("- 수정 동기화 완료 [" + apiInterfaceUI.getEaiSvcName() + "]");

		callCommandIfExists(apiInterfaceUI.getRequestTransform(), "com.eactive.eai.agent.transformer.ReloadTransformCommand");
		callCommandIfExists(apiInterfaceUI.getResponseTransform(), "com.eactive.eai.agent.transformer.ReloadTransformCommand");
		callCommandIfExists(apiInterfaceUI.getInboundRequestLayout(), "com.eactive.eai.agent.transformer.ReloadLayoutCommand");
		callCommandIfExists(apiInterfaceUI.getOutboundRequestLayout(), "com.eactive.eai.agent.transformer.ReloadLayoutCommand");
		callCommandIfExists(apiInterfaceUI.getInboundResponseLayout(), "com.eactive.eai.agent.transformer.ReloadLayoutCommand");
		callCommandIfExists(apiInterfaceUI.getOutboundResponseLayout(), "com.eactive.eai.agent.transformer.ReloadLayoutCommand");
		callCommandIfExists(apiInterfaceUI.getInboundErrResponseLayout(), "com.eactive.eai.agent.transformer.ReloadLayoutCommand");
		callCommandIfExists(apiInterfaceUI.getOutboundErrResponseLayout(), "com.eactive.eai.agent.transformer.ReloadLayoutCommand");
		return resultMap;
	}

	public Map<String, Object> deleteSync(String standardMessageKey, ApiInterfaceUI apiInterfaceUI) throws Exception {
		logger.info("- 삭제 동기화 시작 [" + apiInterfaceUI.getEaiSvcName() + "]");
		//HS04,HS05 내부표준전문
		callCommandIfExists(standardMessageKey, "com.eactive.eai.agent.stdmessage.RemoveSTDMessageCommand");

		//HE01 EAI 메시지 공통부
		CommonCommand cmdHE01 = new CommonCommand("com.eactive.eai.agent.eaimessage.RemoveEAIMessageCommand", apiInterfaceUI.getEaiSvcName());
		HashMap<String, Object> resultMap = agentUtilService.broadcast(cmdHE01);

		// Transform 및 Layout 삭제
		callCommandIfExists(apiInterfaceUI.getRequestTransform(), "com.eactive.eai.agent.transformer.RemoveTransformCommand");
		callCommandIfExists(apiInterfaceUI.getResponseTransform(), "com.eactive.eai.agent.transformer.RemoveTransformCommand");
		callCommandIfExists(apiInterfaceUI.getInboundRequestLayout(), "com.eactive.eai.agent.transformer.RemoveLayoutCommand");
		callCommandIfExists(apiInterfaceUI.getOutboundRequestLayout(), "com.eactive.eai.agent.transformer.RemoveLayoutCommand");
		callCommandIfExists(apiInterfaceUI.getInboundResponseLayout(), "com.eactive.eai.agent.transformer.RemoveLayoutCommand");
		callCommandIfExists(apiInterfaceUI.getOutboundResponseLayout(), "com.eactive.eai.agent.transformer.RemoveLayoutCommand");

		logger.info("- 삭제 동기화 완료 [" + apiInterfaceUI.getEaiSvcName() + "]");
		return resultMap;
	}

	public void callCommandIfExists(String value, String commandName) throws Exception {
		if (StringUtils.isNotBlank(value)) {
			agentUtilService.broadcast(new CommonCommand(commandName, value));
		}
	}

	@PostMapping(value = "/onl/transaction/apim/apiInterfaceMan.excel", params = "cmd=DETAIL_EXPORT_TO_EXCEL")
	public ResponseEntity<byte[]> detailExportToExcel(@RequestParam(name = "eaiSvcName") String eaiSvcName) throws Exception {
		// 단일 파일 처리
		ApiInterfaceExportData exportData = service.exportInterfaceToExcel(eaiSvcName); // Excel 파일 내용 생성 함수(가정)
		ApiInterfaceUI selectedUI = exportData.getApiInterfaceUI();
		String fileName = eaiSvcName + "(" + selectedUI.getEaiSvcDesc() + ").xlsx";
		fileName = FilenameUtils.normalize(fileName);
		fileName = URLEncoder.encode(fileName, "UTF-8");

		HttpHeaders headers = new HttpHeaders();
		headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
		headers.add(HttpHeaders.CONTENT_TYPE, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");

		return ResponseEntity.ok()
				.headers(headers)
				.body(exportData.getExportFileContent());
	}

	@PostMapping(value = "/onl/transaction/apim/apiInterfaceMan.file", params = "cmd=LIST_IMPORT_FILE")
	public ResponseEntity<?>  listImportFromJson(@RequestParam("file") MultipartFile file, boolean importDupliCheck) {
		try {
			if (file != null) {
				String extension = FilenameUtils.getExtension(file.getOriginalFilename()).toLowerCase();
				if("json".equals(extension)) {
					ApiInterfaceReloadSyncSet apiInterfaceExportSetUI = service.importInterfaceFromJson(file, importDupliCheck);
					reloadSync(apiInterfaceExportSetUI.getApiInterfaceUI());
					return ResponseEntity.ok().body("File successfully imported");
				} else {
					throw new IllegalStateException("파일 [ " + file.getOriginalFilename() + " ] 의 확장자가 JSON 이 아닙니다. 다시 시도하세요.");
				}
			}
		} catch (IllegalStateException dupEx) {
			return ResponseEntity
					.status(HttpStatus.CONFLICT)
					.body(dupEx.getMessage());
		} catch (Exception e) {
			logger.error("Error processing file", e);
			return ResponseEntity.internalServerError().body("Error processing file - "+e.getMessage() );
		}
		return ResponseEntity.internalServerError().body("empty file or unmatched extension");
	}

	@PostMapping(value = "/onl/transaction/apim/apiInterfaceMan.json", params = "cmd=DETAIL_EXPORT_TO_JSON")
	public ResponseEntity<byte[]> detailExportToJson(@RequestParam(name = "eaiSvcName") String eaiSvcName) throws Exception {
		// 단일 파일 처리
		ApiInterfaceExportData exportData = service.exportInterfaceToJson(eaiSvcName);

		ApiInterfaceUI selectedUI = exportData.getApiInterfaceUI();
		String fileName = eaiSvcName + "(" + selectedUI.getEaiSvcDesc() + ").json";
		fileName = FilenameUtils.normalize(fileName);
		fileName = URLEncoder.encode(fileName, "UTF-8");

		HttpHeaders headers = new HttpHeaders();
		headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
		headers.add(HttpHeaders.CONTENT_TYPE, "application/json");

		return ResponseEntity.ok()
				.headers(headers)
				.body(exportData.getExportFileContent());
	}

	@PostMapping(value = "/onl/transaction/apim/apiInterfaceMan.json", params = "cmd=CLONE")
	public ResponseEntity<?>  cloneApiInterface(String orgApiInterfaceId, String newBizCode,
												String newApiInterfaceId, String newInboundHttpMethod,
												String newInboundRestPath, String newSvcDesc, boolean importDupliCheck) throws BizException {
		try {
			ApiInterfaceUI orgApiInterfaceUI = service.selectDetail(orgApiInterfaceId);
			ApiInterfaceUI apiInterfaceUI = service.cloneApiInterface(orgApiInterfaceUI, newBizCode, newApiInterfaceId, newInboundHttpMethod, newInboundRestPath, newSvcDesc, importDupliCheck);
			Map<String, Object> resultMap = reloadSync(apiInterfaceUI);
			return ResponseEntity.ok(resultMap);
		} catch(Exception e) {
			if(e instanceof DuplicateKeyException) {
				DuplicateKeyException dupEx = (DuplicateKeyException) e;
				Throwable cause = dupEx.getMostSpecificCause();
				throw new BizException("중복 오류가 발생했습니다. 확인바랍니다. 오류메시지: "+cause.getMessage());
			}
			logger.error(e);
			throw new BizException("오류가 발생했습니다. 확인바랍니다. 오류메시지: "+e.getMessage());
		}
	}
}
