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

import com.eactive.apim.portal.portalorg.entity.PortalOrg;
import com.eactive.apim.portal.portalorg.entity.PortalOrgEnums;
import com.eactive.eai.data.entity.onl.transformer.layout.LayoutEntity;
import com.eactive.eai.rms.common.base.OnlBaseAnnotationController;
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.vo.GridResponse;
import com.eactive.eai.rms.data.entity.onl.apim.portalorg.PortalOrgUISearch;
import com.eactive.eai.rms.data.entity.onl.layout.LayoutService;
import com.eactive.eai.rms.onl.apim.portalorg.PortalOrgManService;
import com.eactive.eai.rms.onl.apim.portalorg.PortalOrgUI;
import com.eactive.eai.rms.onl.common.exception.BizException;
import com.eactive.eai.rms.onl.manage.rule.layout.mapper.LayoutUIMapper;
import com.eactive.eai.rms.onl.manage.rule.layout.ui.LayoutUI;
import com.eactive.eai.rms.onl.transaction.apim.ui.ApiInterfaceUI;
import com.eactive.eai.rms.onl.transaction.apim.ui.ApiSpecInfoUI;

import java.util.*;
import java.util.stream.Collectors;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.web.SortDefault;
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;

@Controller
public class ApiSpecController extends OnlBaseAnnotationController {

    @Autowired
    ApiSpecManService apiSpecManService;

    @Autowired
    PortalOrgManService portalOrgManService;

    @Autowired
    ApiInterfaceService apiInterfaceService;

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

    @GetMapping(value = "/onl/transaction/apim/apiSpecMan.view", params = "cmd=POPUP_LIST")
    public String detailOrgPopupView() {
        return "/onl/transaction/apim/apiSpecManDisplayOrgPopup";
    }

    @PostMapping(value = "/onl/transaction/apim/apiSpecMan.json", params = "cmd=DETAIL")
    public ResponseEntity<ApiSpecInfoUI> selectDetail(String eaiSvcName) {
        ApiSpecInfoUI specInfo = apiSpecManService.selectDetail(eaiSvcName);

        if (StringUtils.isNotBlank(specInfo.getDisplayOrg())) {
            String orgNames = Arrays.stream(specInfo.getDisplayOrg().split(","))
                    .map(orgId -> portalOrgManService.findById(orgId))
                    .filter(Optional::isPresent)
                    .map(Optional::get)
                    .map(PortalOrg::getOrgName)
                    .filter(Objects::nonNull)
                    .collect(Collectors.joining(", "));

            specInfo.setOrgName(orgNames);
        }

        return ResponseEntity.ok(specInfo);
    }

    @PostMapping(value = "/onl/transaction/apim/apiSpecMan.json", params = "cmd=INSERT")
    public ResponseEntity<Map<String, Object>> save(ApiSpecInfoUI apiSpecInfoUI) throws Exception {
        try {
            apiSpecInfoUI.setApiRequestSpec(StringEscapeUtils.unescapeHtml(apiSpecInfoUI.getApiRequestSpec()));
            apiSpecInfoUI.setApiResponseSpec(StringEscapeUtils.unescapeHtml(apiSpecInfoUI.getApiResponseSpec()));
            apiSpecInfoUI.setDescription(StringEscapeUtils.unescapeHtml(apiSpecInfoUI.getDescription()));
            apiSpecInfoUI.setTestbedSpec(StringEscapeUtils.unescapeHtml(apiSpecInfoUI.getTestbedSpec()));

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

    @PostMapping(value = "/onl/transaction/apim/apiSpecMan.json", params = "cmd=DELETE")
    public ResponseEntity<Map<String, Object>> delete(ApiSpecInfoUI apiSpecInfoUI) throws Exception {
        try {
            apiSpecManService.delete(apiSpecInfoUI);
            return ResponseEntity.ok().build();
        } catch (Exception e) {
            if (e instanceof BizException) {
                throw e;
            }
            throw new BizException("오류가 발생했습니다. 확인바랍니다. error:" + e.getMessage(), e);
        }
    }
    @PostMapping(value = "/onl/transaction/apim/apiSpecMan.json", params = "cmd=GENERATE_SPEC")
    public ResponseEntity<Map<String, String>> generateSpec(ApiSpecInfoUI apiSpecInfoUI) {
        try {
            if (apiSpecInfoUI == null || StringUtils.isEmpty(apiSpecInfoUI.getApiId())) {
                throw new BizException("API ID가 존재하지 않습니다.");
            }

            ApiInterfaceUI apiInterfaceUI = apiInterfaceService.selectDetail(apiSpecInfoUI.getApiId());
            if (apiInterfaceUI == null) {
                throw new BizException("API 인터페이스 정보를 찾을 수 없습니다.");
            }

            Map<String, String> inboundAdapterSpec = apiInterfaceService.getHttpAdapterInfo(apiInterfaceUI.getFromAdapter());
            if (inboundAdapterSpec == null) {
                inboundAdapterSpec = new HashMap<>();
            }

            String requestLayoutName = apiInterfaceUI.getInboundRequestLayout();
            String responseLayoutName = apiInterfaceUI.getInboundResponseLayout();

            // Layout 정보 조회. 없으면 null.
            LayoutUI requestLayoutUI = StringUtils.isNotEmpty(requestLayoutName) ?
                    apiSpecManService.selectLayoutUI(requestLayoutName) : null;
            LayoutUI responseLayoutUI = StringUtils.isNotEmpty(responseLayoutName) ?
                    apiSpecManService.selectLayoutUI(responseLayoutName) : null;

            Map<String, String> result = new HashMap<>();

            // Layout이 없어도 generateSpecTableFromLayout과 generateSampleDataFromLayout 메서드를 호출
            // 각 메서드 내부에서 샘플 레이아웃을 생성하여 처리
            result.put("requestSpec", apiSpecManService.generateSpecTableFromLayout(requestLayoutUI));
            result.put("responseSpec", apiSpecManService.generateSpecTableFromLayout(responseLayoutUI));
            result.put("sampleRequest", apiSpecManService.generateSampleDataFromLayout(requestLayoutUI));
            result.put("sampleResponse", apiSpecManService.generateSampleDataFromLayout(responseLayoutUI));

            // Swagger/OpenAPI 스펙 생성
            String swaggerSpec = apiSpecManService.generateSwaggerSpec(requestLayoutUI, responseLayoutUI,
                    inboundAdapterSpec, apiInterfaceUI);
            result.put("testbedSpec", swaggerSpec);

            return ResponseEntity.ok(result);
        } catch (BizException e) {
            throw e;
        } catch (Exception e) {
            logger.error("API 스펙 생성 중 오류 발생", e);
            throw new BizException("API 스펙 생성 중 오류가 발생했습니다: " + e.getMessage(), e);
        }
    }
}
