package com.interplug.qcast.biz.community;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.util.StreamUtils;
import org.springframework.web.util.UriComponentsBuilder;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.interplug.qcast.biz.community.dto.BoardRequest;
import com.interplug.qcast.biz.community.dto.BoardResponse;
import com.interplug.qcast.config.Exception.ErrorCode;
import com.interplug.qcast.config.Exception.QcastException;
import com.interplug.qcast.config.message.Messages;
import com.interplug.qcast.util.InterfaceQsp;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j
@Service
@RequiredArgsConstructor
public class BoardService {

  private final InterfaceQsp interfaceQsp;
  @Autowired
  Messages message;

  @Value("${qsp.url}")
  private String QSP_API_URL;

  /**
   * ※ 게시판 목록 조회 QSP -> Q.CAST3
   *
   * @param boardRequest
   * @return
   * @throws Exception
   */
  public BoardResponse getBoardList(BoardRequest boardRequest) throws Exception {

    BoardResponse response = null;

    /* [0]. Validation Check */
    if ("".equals(boardRequest.getSchNoticeClsCd())) {
      // [msg] {0} is required input value.
      throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Notice Cls Code"));
    }
    if ("".equals(boardRequest.getSchNoticeTpCd())) {
      // [msg] {0} is required input value.
      throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Notice Type Code"));
    }

    /* [1]. QSP API (url + param) Setting */
    String encodedSchTitle = "";
    if (!"".equals(boardRequest.getSchTitle()) && boardRequest.getSchTitle() != null) {
      encodedSchTitle = URLEncoder.encode(boardRequest.getSchTitle(), StandardCharsets.UTF_8);
    }

    String url = QSP_API_URL + "/api/board/list";
    String apiUrl = UriComponentsBuilder.fromHttpUrl(url)
        .queryParam("noticeNo", boardRequest.getNoticeNo()).queryParam("schTitle", encodedSchTitle)
        .queryParam("schNoticeTpCd", boardRequest.getSchNoticeTpCd())
        .queryParam("schNoticeClsCd", boardRequest.getSchNoticeClsCd())
        .queryParam("startRow", boardRequest.getStartRow())
        .queryParam("endRow", boardRequest.getEndRow()).build().toUriString();

    /* [2]. QSP API CALL -> Response */
    String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null);

    if (!"".equals(strResponse)) {
      ObjectMapper om =
          new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

      response = om.readValue(strResponse, BoardResponse.class);
    } else {
      // [msg] No data
      throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data"));
    }

    return response;
  }

  /**
   * ※ 게시판 상세 조회 QSP -> Q.CAST3
   *
   * @param boardRequest
   * @return
   * @throws Exception
   */
  public BoardResponse getBoardDetail(BoardRequest boardRequest) throws Exception {

    BoardResponse response = null;

    /* [0]. Validation Check */
    if (boardRequest.getNoticeNo() == null) {
      // [msg] {0} is required input value.
      throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "Notice No"));
    }

    /* [1]. QSP API (url + param) Setting */
    String url = QSP_API_URL + "/api/board/detail";
    String apiUrl = UriComponentsBuilder.fromHttpUrl(url)
        .queryParam("noticeNo", boardRequest.getNoticeNo()).build().toUriString();

    /* [2]. QSP API CALL -> Response */
    String strResponse = interfaceQsp.callApi(HttpMethod.GET, apiUrl, null);

    if (!"".equals(strResponse)) {
      ObjectMapper om =
          new ObjectMapper().configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

      response = om.readValue(strResponse, BoardResponse.class);
    } else {
      // [msg] No data
      throw new QcastException(ErrorCode.NOT_FOUND, message.getMessage("common.message.no.data"));
    }

    return response;
  }

  /**
   * ※ 게시판 파일 다운로드 QSP -> Q.CAST3
   *
   * @param response
   * @param encodeFileNo
   * @throws Exception
   */
  public void getFileDownload(HttpServletResponse response, String encodeFileNo) throws Exception {

    /* [0]. Validation Check */
    if ("".equals(encodeFileNo)) {
      // [msg] {0} is required input value.
      throw new QcastException(ErrorCode.INVALID_INPUT_VALUE,
          message.getMessage("common.message.required.data", "File No"));
    }

    /* [1]. QSP API (url + fileNo) Setting */
    String url = QSP_API_URL + "/api/file/downloadFile" + "?encodeFileNo=" + encodeFileNo;

    /* [2]. QSP API CALL -> Response */
    Map<String, String> result = new HashMap<String, String>();
    byte[] byteResponse = interfaceQsp.callApi(HttpMethod.GET, url, null, result);

    if (byteResponse != null && byteResponse.length > 0) {
      try {
        /* [3]. API 응답 파일 처리 */
        response.setContentType(
            !"".equals(result.get("type")) && result.get("type") != null ? result.get("type")
                : "application/octet-stream");
        response.setHeader("Content-Disposition",
            !"".equals(result.get("disposition")) && result.get("disposition") != null
                ? result.get("disposition")
                : "attachment;");

        InputStream inputStream = new ByteArrayInputStream(byteResponse);
        StreamUtils.copy(inputStream, response.getOutputStream());

        response.flushBuffer();
        inputStream.close();

      } catch (Exception e) {
        // [msg] File download error
        throw new QcastException(ErrorCode.INTERNAL_SERVER_ERROR,
            message.getMessage("common.message.file.download.error"));
      }

    } else {
      // [msg] File does not exist.
      throw new QcastException(ErrorCode.NOT_FOUND,
          message.getMessage("common.message.file.download.exists"));
    }
  }
}
