package go.kr.project.system.execquery.controller;

import egovframework.constant.TilesConstants;
import go.kr.project.system.execquery.model.QueryRequest;
import go.kr.project.system.execquery.model.QueryResponse;
import go.kr.project.system.execquery.service.DbQueryService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

@Slf4j
@RequiredArgsConstructor
@Controller
@RequestMapping("/db/exec")
public class DbQueryController {

    private final DbQueryService dbQueryService;

    /**
     * <pre>메소드 설명: 메인 페이지</pre>
     * @param req
     * @return String 요청처리 후 응답객체
     * @author: 최정민
     * @date: 2021. 9. 27.
     */
    @GetMapping(value = "query.do")
    public String query(HttpServletRequest req, Model model) {

        return "system/db/exec" + TilesConstants.BASE;
    }

    @PostMapping("/queryexec.do")
    public ResponseEntity<QueryResponse> executeQuery(
            @RequestBody QueryRequest request,
            HttpServletRequest httpRequest) {

        try {
            // Base64 인코딩된 쿼리가 있으면 디코딩
            if (request.isBase64Encoded() && request.getQuery() != null) {
                String base64Query = request.getQuery();
                log.info("Base64 인코딩된 쿼리 수신: {}", base64Query);

                // Base64 디코딩
                byte[] decodedBytes = Base64.getDecoder().decode(base64Query);
                String decodedQuery = new String(decodedBytes, StandardCharsets.UTF_8);

                log.info("디코딩된 쿼리: {}", decodedQuery);
                // 개별 쿼리를 받으므로 세미콜론 제거 로직을 수정
                // 쿼리 끝의 세미콜론만 제거 (중간에 있는 세미콜론은 유지)
                String cleanedQuery = decodedQuery.trim();
                if (cleanedQuery.endsWith(";")) {
                    cleanedQuery = cleanedQuery.substring(0, cleanedQuery.length() - 1).trim();
                }
                request.setQuery(cleanedQuery);
            }

            // 세션 ID 추가
            HttpSession session = httpRequest.getSession(true);
            request.setSessionId(session.getId());

            // SQL 쿼리 실행 전 로깅
            log.info("쿼리 실행 요청: 타입={}, 트랜잭션ID={}, 세션ID={}",
                    request.getQueryType(), request.getTransactionId(), session.getId());

            QueryResponse response = dbQueryService.executeQuery(request);

            // 응답 로깅
            log.info("쿼리 실행 결과: 성공={}, 행수={}, 트랜잭션ID={}",
                    response.isSuccess(), response.getRowsAffected(), response.getTransactionId());

            return ResponseEntity.ok(response);
        } catch (Exception e) {
            log.error("쿼리 실행 중 오류 발생", e);
            QueryResponse errorResponse = new QueryResponse();
            errorResponse.setSuccess(false);
            errorResponse.setMessage("쿼리 실행 중 오류: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(errorResponse);
        }

    }
}
