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

import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
import com.eactive.eai.rms.onl.apim.common.BaseRestController;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
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.ResponseBody;

import java.util.List;

/**
 * OBP API 목록 조회 REST Controller
 *
 * <p>TSEAIHE01과 TSEAIHS04를 조인하여 API 정보를 JSON으로 제공</p>
 *
 * @see BaseRestController 세션 체크 우회 및 JSON 유틸리티 제공
 */
@Controller
public class ObpApiController extends BaseRestController {

    private static final Logger log = LoggerFactory.getLogger(ObpApiController.class);

    private final ObpApiService obpApiService;

    public ObpApiController(ObpApiService obpApiService) {
        this.obpApiService = obpApiService;
    }

    /**
     * OBP API 전체 목록 조회 (v2)
     *
     * @param providerCode Provider 코드 (KJB만 허용, 대소문자 무시)
     * @param pretty       true면 JSON 들여쓰기 적용
     * @return JSON Array
     */
    @RequestMapping(value = "/apis/{providerCode}", method = RequestMethod.GET, produces = JSON_CONTENT_TYPE)
    @ResponseBody
    public String getApisV2(
            @PathVariable("providerCode") String providerCode,
            @RequestParam(value = "pretty", required = false) Boolean pretty) {

        log.debug("OBP API 목록 조회 요청 (v2): providerCode={}, pretty={}", providerCode, pretty);
        long startTime = System.currentTimeMillis();

        // 1. providerCode 검증
        ProviderCodeValidator.validateProviderCode(providerCode);

        // 2. 데이터소스 설정
        DataSourceContextHolder.setDataSourceType(
                DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.APIGW));

        try {
            List<ObpApiDTO> apis = obpApiService.findAllApis();

            String json = toJson(apis, pretty);

            long elapsed = System.currentTimeMillis() - startTime;
            log.info("OBP API 목록 조회 완료 (v2): providerCode={}, count={}, size={}, elapsed={}ms",
                    providerCode, apis.size(), getFormattedJsonSize(json), elapsed);

            return json;

        } catch (Exception e) {
            log.error("OBP API 목록 조회 실패 (v2): providerCode={}", providerCode, e);
            throw e;
        }
    }

    /**
     * OBP API 목록 조회 (기관별, v2)
     *
     * @param orgCode      기관코드 (OBP 파트너코드)
     * @param providerCode Provider 코드 (KJB만 허용, 대소문자 무시)
     * @param pretty       true면 JSON 들여쓰기 적용
     * @return JSON Array (기관 미존재 시 빈 배열)
     */
    @RequestMapping(
        value = "/apis/{orgCode}/{providerCode}",
        method = RequestMethod.GET,
        produces = JSON_CONTENT_TYPE
    )
    @ResponseBody
    public String getApisByOrgCodeAndProvider(
            @PathVariable("orgCode") String orgCode,
            @PathVariable("providerCode") String providerCode,
            @RequestParam(value = "pretty", required = false) Boolean pretty) {

        log.debug("OBP API 목록 조회 요청 (기관별): orgCode={}, providerCode={}, pretty={}",
                orgCode, providerCode, pretty);
        long startTime = System.currentTimeMillis();

        // 1. providerCode 검증
        ProviderCodeValidator.validateProviderCode(providerCode);

        // 2. 데이터소스 설정
        DataSourceContextHolder.setDataSourceType(
                DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.APIGW));

        try {
            // 3. 기관별 API 조회
            List<ObpApiDTO> apis = obpApiService.findApisByOrgCode(orgCode);

            String json = toJson(apis, pretty);

            long elapsed = System.currentTimeMillis() - startTime;
            log.info("OBP API 목록 조회 완료 (기관별): orgCode={}, providerCode={}, count={}, size={}, elapsed={}ms",
                    orgCode, providerCode, apis.size(), getFormattedJsonSize(json), elapsed);

            return json;

        } catch (Exception e) {
            log.error("OBP API 목록 조회 실패 (기관별): orgCode={}, providerCode={}",
                    orgCode, providerCode, e);
            throw e;
        }
    }

    /**
     * 전체 API 목록 조회
     *
     * @param pretty true면 JSON 들여쓰기 적용
     * @return JSON Array
     * @deprecated Use {@link #getApisV2(String, Boolean)} instead.
     *             Will be removed in next major version.
     */
    @Deprecated
    @RequestMapping(
            value = "/kjb/apis.json",
            produces = JSON_CONTENT_TYPE
    )
    @ResponseBody
    public String getApis(
            @RequestParam(value = "pretty", required = false) Boolean pretty
    ) {
        log.debug("OBP API 목록 조회 요청: pretty={}", pretty);
        long startTime = System.currentTimeMillis();

        // APIGW 데이터소스 강제 설정
        DataSourceContextHolder.setDataSourceType(
                DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.APIGW));


        try {
            List<ObpApiDTO> apis = obpApiService.findAllApis();

            String json = toJson(apis, pretty);

            long elapsed = System.currentTimeMillis() - startTime;
            log.info("OBP API 목록 조회 완료: count={}, size={}, elapsed={}ms",
                    apis.size(), getFormattedJsonSize(json), elapsed);

            return json;

        } catch (Exception e) {
            log.error("OBP API 목록 조회 실패", e);
            throw e;
        }
    }

    /**
     * 기관코드별 API 목록 조회
     *
     * <p>해당 기관의 활성 앱(appstatus='1')이 사용하는 API만 반환</p>
     *
     * @param orgCode 기관코드 (OBP 파트너코드)
     * @param pretty true면 JSON 들여쓰기 적용
     * @return JSON Array (기관 미존재 시 빈 배열)
     * @deprecated Use {@link #getApisByOrgCodeAndProvider(String, String, Boolean)} instead.
     *             Migrate to /api/apis/{orgCode}/{providerCode}
     *             Will be removed in next major version.
     */
    @Deprecated
    @RequestMapping(
            value = "/kjb/{orgCode}/apis.json",
            produces = JSON_CONTENT_TYPE
    )
    @ResponseBody
    public String getApisByOrgCode(
            @PathVariable("orgCode") String orgCode,
            @RequestParam(value = "pretty", required = false) Boolean pretty
    ) {
        log.debug("OBP API 목록 조회 요청 (기관별): orgCode={}, pretty={}", orgCode, pretty);
        long startTime = System.currentTimeMillis();

        // APIGW 데이터소스 강제 설정
        DataSourceContextHolder.setDataSourceType(
                DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.APIGW));

        try {
            List<ObpApiDTO> apis = obpApiService.findApisByOrgCode(orgCode);

            String json = toJson(apis, pretty);

            long elapsed = System.currentTimeMillis() - startTime;
            log.info("OBP API 목록 조회 완료 (기관별): orgCode={}, count={}, size={}, elapsed={}ms",
                    orgCode, apis.size(), getFormattedJsonSize(json), elapsed);

            return json;

        } catch (Exception e) {
            log.error("OBP API 목록 조회 실패 (기관별): orgCode={}", orgCode, e);
            throw e;
        }
    }
}
