package com.aip.gateway.api.controller;

import com.aip.gateway.api.dto.LinkedApiKeyDto;
import com.aip.gateway.api.dto.LinkedDecryptKeyDto;
import com.aip.gateway.api.dto.LinkedServerDto;
import com.aip.gateway.api.dto.LinkedSystemDto;
import com.aip.gateway.api.model.response.ApiResponseModel;
import com.aip.gateway.api.repository.AppRepository;
import com.aip.gateway.api.repository.GlobalConstants;
import com.aip.gateway.api.service.IApiDbService;
import io.swagger.annotations.ApiOperation;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@Slf4j
@Tag(name = "ApiDb", description = "DB API")
@RestController
@RequiredArgsConstructor
@CrossOrigin
@Validated
@RequestMapping("/v1/aip-api/db")
public class ApiDbController extends  BaseController {

    private final AppRepository appRepo;
    private final IApiDbService service;

    @Operation(summary = "Db Reload", description = "Db Reload API.")
    @ApiResponse(responseCode = "200", description = "DB Re Loading Success.")
    @ApiOperation(value = "Db Reload", response = ApiResponseModel.class)
    @PostMapping(value = "reload", produces = {"application/json; charset=utf8"})
    public ResponseEntity<ApiResponseModel> reloadDatabase(
            @Parameter(name = "apiKey", description = "API Key", example = "24826125-188B-4875-A841-F9146DD267F0", required = true)
            @RequestParam("apiKey") String apiKey,
            HttpServletRequest request)
    {
        try {
            GlobalConstants.setAuthorization(request, GlobalConstants.API_DB_RELOAD, apiKey, null);
            int authError = this.appRepo.checkApiKeyValidation(apiKey, getRemoteIP(request));
            if (authError != 0) {
                return responseApiKeyValidationError(request, authError);
            }
            return responseSuccess(this.service.reloadDatabase());
        }
        catch (Exception e) {
            log.error("exception: /v1/aip-api/db/reload, {}", e.getMessage());
            return responseException(request, e);
        }
    }

    @Operation(summary = "연계 시스템 조회", description = "연계 시스템 조회.")
    @ApiResponse(responseCode = "200", description = "Linked System query success.")
    @ApiOperation(value = "연계 시스템 조회", response = ApiResponseModel.class, responseContainer = "ArrayList")
    @GetMapping(value = "linked-systems", produces = {"application/json; charset=utf8"})
    public ResponseEntity<ApiResponseModel> getLinkedSystems(
            @Parameter(name = "apiKey", description = "API Key", example = "24826125-188B-4875-A841-F9146DD267F0", required = true) String apiKey,
            HttpServletRequest request)
    {
        try {
            GlobalConstants.setAuthorization(request, GlobalConstants.API_DB_LINKED_SYSTEMS, apiKey, null);
            int authError = this.appRepo.checkApiKeyValidation(apiKey, getRemoteIP(request));
            if (authError != 0) {
                return responseApiKeyValidationError(request, authError);
            }
            List<LinkedSystemDto> response = this.service.getLinkedSystems();
            return ResponseEntity.ok().body(ApiResponseModel.builder()
                    .success(true)
                    .statusCode(HttpStatus.OK.value())
                    .message("success")
                    .result(response)
                    .build());
        }
        catch (Exception e) {
            log.error("exception: /v1/aip-api/db/linked-systems, {}", e.getMessage());
            return responseException(request, e);
        }
    }

    @Operation(summary = "연계 서버 조회", description = "연계 서버 조회.")
    @ApiResponse(responseCode = "200", description = "Linked Server query success.")
    @ApiOperation(value = "연계 서버 조회", response = ApiResponseModel.class, responseContainer = "ArrayList")
    @GetMapping(value = "linked-servers", produces = {"application/json; charset=utf8"})
    public ResponseEntity<ApiResponseModel> getLinkedServers(
            @Parameter(name = "apiKey", description = "API Key", example = "24826125-188B-4875-A841-F9146DD267F0", required = true) String apiKey,
            HttpServletRequest request)
    {
        try {
            GlobalConstants.setAuthorization(request, GlobalConstants.API_DB_LINKED_SERVERS, apiKey, null);
            int authError = this.appRepo.checkApiKeyValidation(apiKey, getRemoteIP(request));
            if (authError != 0) {
                return responseApiKeyValidationError(request, authError);
            }
            List<LinkedServerDto> response = this.service.getLinkedServers();
            return ResponseEntity.ok().body(ApiResponseModel.builder()
                    .success(true)
                    .statusCode(HttpStatus.OK.value())
                    .message("success")
                    .result(response)
                    .build());
        }
        catch (Exception e) {
            log.error("exception: /v1/aip-api/db/linked-servers, {}", e.getMessage());
            return responseException(request, e);
        }
    }

    @Operation(summary = "연계 서버 API KEY 조회", description = "연계 서버 API KEY 조회.")
    @ApiResponse(responseCode = "200", description = "Linked Server API KEY query success.")
    @ApiOperation(value = "연계 서버 API KEY 조회", response = ApiResponseModel.class, responseContainer = "ArrayList")
    @GetMapping(value = "linked-api-keys", produces = {"application/json; charset=utf8"})
    public ResponseEntity<ApiResponseModel> getLinkedApiKeys(
            @Parameter(name = "apiKey", description = "API Key", example = "24826125-188B-4875-A841-F9146DD267F0", required = true) String apiKey,
            HttpServletRequest request)
    {
        try {
            GlobalConstants.setAuthorization(request, GlobalConstants.API_DB_LINKED_API_KEYS, apiKey, null);
            int authError = this.appRepo.checkApiKeyValidation(apiKey, getRemoteIP(request));
            if (authError != 0) {
                return responseApiKeyValidationError(request, authError);
            }
            List<LinkedApiKeyDto> response = this.service.getLinkedApiKeys();
            return ResponseEntity.ok().body(ApiResponseModel.builder()
                    .success(true)
                    .statusCode(HttpStatus.OK.value())
                    .message("success")
                    .result(response)
                    .build());
        }
        catch (Exception e) {
            log.error("exception: /v1/aip-api/db/linked-api-keys, {}", e.getMessage());
            return responseException(request, e);
        }
    }

    @Operation(summary = "연계 서버 Decrypt KEY 조회", description = "연계 서버 Decrypt KEY 조회.")
    @ApiResponse(responseCode = "200", description = "Linked Server Decrypt KEY query success.")
    @ApiOperation(value = "연계 서버 Decrypt KEY 조회", response = ApiResponseModel.class, responseContainer = "ArrayList")
    @GetMapping(value = "linked-decrypt-keys", produces = {"application/json; charset=utf8"})
    public ResponseEntity<ApiResponseModel> getLinkedDecryptKeys(
            @Parameter(name = "apiKey", description = "API Key", example = "24826125-188B-4875-A841-F9146DD267F0", required = true) String apiKey,
            HttpServletRequest request)
    {
        try {
            GlobalConstants.setAuthorization(request, GlobalConstants.API_DB_LINKED_DECRYPT_KEYS, apiKey, null);
            int authError = this.appRepo.checkApiKeyValidation(apiKey, getRemoteIP(request));
            if (authError != 0) {
                return responseApiKeyValidationError(request, authError);
            }
            List<LinkedDecryptKeyDto> response = this.service.getLinkedDecryptKeys();
            return ResponseEntity.ok().body(ApiResponseModel.builder()
                    .success(true)
                    .statusCode(HttpStatus.OK.value())
                    .message("success")
                    .result(response)
                    .build());
        }
        catch (Exception e) {
            log.error("exception: /v1/aip-api/db/linked-decrypt-keys, {}", e.getMessage());
            return responseException(request, e);
        }
    }

}
