package kr.xit.batch.ens.web;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParameter;
import org.springframework.batch.core.JobParameters;
import org.springframework.batch.core.JobParametersInvalidException;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.batch.core.repository.JobExecutionAlreadyRunningException;
import org.springframework.batch.core.repository.JobInstanceAlreadyCompleteException;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.ExampleObject;
import io.swagger.v3.oas.annotations.tags.Tag;
import kr.xit.batch.ens.job.KtGbsAccessTokenUpdateJobConfig;
import kr.xit.batch.ens.job.SndngAcceptJobConfig;
import kr.xit.batch.ens.job.SndngCloseJobConfig;
import kr.xit.batch.ens.job.SndngMakeJobConfig;
import kr.xit.batch.ens.job.SndngSnedBulksJobConfig;
import kr.xit.batch.ens.job.SndngStatusBulksJobConfig;
import kr.xit.biz.common.ApiConstants;
import kr.xit.biz.ens.model.cmm.CmmEnsRequestDTO;
import kr.xit.core.model.ApiResponseDTO;
import kr.xit.core.model.IApiResponse;
import kr.xit.core.support.utils.Checks;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * <pre>
 * description : 카카오페이 전자문서 발송요청 배치 컨트롤러
 *
 * packageName : kr.xit.batch.ens.web
 * fileName    : KkopayEltrcDocBatchController
 * author      : limju
 * date        : 2023-05-16
 * ======================================================================
 * 변경일         변경자        변경 내용
 * ----------------------------------------------------------------------
 * 2023-05-16    limju       최초 생성
 *
 * </pre>
 */
@Tag(name = "BatchJobWebController", description = "전자고지 통합발송 배치 WEB")
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/batch/v1")
public class BatchJobWebController {
    @Value("${app.slack-webhook.enabled:false}")
    private String isSlackEnabled;

    @SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection")
    private final JobLauncher jobLauncher;
    private final SndngAcceptJobConfig acceptJobConfig;
    private final SndngMakeJobConfig makeJobConfig;
    private final SndngSnedBulksJobConfig sendBulksJobConfig;
    private final SndngStatusBulksJobConfig statusJobConfig;
    private final SndngCloseJobConfig closeJobConfig;
    private final KtGbsAccessTokenUpdateJobConfig tokenUpdateJobConfig;

    private static final String CAN_1 = """
                        {
                          "signguCode": "44131",
                          "ffnlgCode": "11",
                          "profile": "local"
                        }
                    """;
    private static final String CAN_2 = """
                        {
                          "signguCode": "44133",
                          "ffnlgCode": "11",
                          "profile": "local"
                        }
                    """;

    private static final String CCN = """
                        {
                          "signguCode": "51110",
                          "ffnlgCode": "11",
                          "profile": "local"
                        }
                    """;

    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
        @Content(
            mediaType = "application/json",
            examples = {
                @ExampleObject(
                    name = "춘천",
                    value = CCN),
                @ExampleObject(
                    name = "천안시 동남구청",
                    value = CAN_1),
                @ExampleObject(
                    name = "천안시 서북구청",
                    value = CAN_2)
            })
    })
    @Operation(summary = "accept", description = "accept")
    @PostMapping(value = "/accept", produces = MediaType.APPLICATION_JSON_VALUE)
    public IApiResponse accept(@RequestBody final CmmEnsRequestDTO reqDTO) {
        try {
            JobExecution jobExecution = jobLauncher.run(
                acceptJobConfig.sndngAcceptJob(),
                getJobParameters(reqDTO, ApiConstants.SndngProcessStatus.ACCEPT.getCode())
            );

            while(jobExecution.isRunning()){
                log.info("...");
            }
            printLog(jobExecution);

        } catch (JobExecutionAlreadyRunningException | JobInstanceAlreadyCompleteException
                 | JobParametersInvalidException | org.springframework.batch.core.repository.JobRestartException e) {

            log.error(e.getMessage());
        }
        return ApiResponseDTO.success(HttpStatus.OK);
    }

    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
        @Content(
            mediaType = "application/json",
            examples = {
                @ExampleObject(
                    name = "춘천",
                    value = CCN),
                @ExampleObject(
                    name = "천안시 동남구청",
                    value = CAN_1),
                @ExampleObject(
                    name = "천안시 서북구청",
                    value = CAN_2)
            })
    })
    @Operation(summary = "make", description = "make")
    @PostMapping(value = "/make", produces = MediaType.APPLICATION_JSON_VALUE)
    public IApiResponse make(@RequestBody final CmmEnsRequestDTO reqDTO) {

        try {
            JobExecution jobExecution = jobLauncher.run(
                makeJobConfig.sndngMakeJob(),
                getJobParameters(reqDTO, ApiConstants.SndngProcessStatus.ACCEPT_OK.getCode())
            );

            while(jobExecution.isRunning()){
                log.info("...");
            }
            printLog(jobExecution);

        } catch (JobExecutionAlreadyRunningException | JobInstanceAlreadyCompleteException
                 | JobParametersInvalidException | org.springframework.batch.core.repository.JobRestartException e) {

            log.error(e.getMessage());
        }
        return ApiResponseDTO.success(HttpStatus.OK);
    }

    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
        @Content(
            mediaType = "application/json",
            examples = {
                @ExampleObject(
                    name = "춘천",
                    value = CCN),
                @ExampleObject(
                    name = "천안시 동남구청",
                    value = CAN_1),
                @ExampleObject(
                    name = "천안시 서북구청",
                    value = CAN_2)
            })
    })
    @Operation(summary = "close", description = "close")
    @PostMapping(value = "/close", produces = MediaType.APPLICATION_JSON_VALUE)
    public IApiResponse close(@RequestBody final CmmEnsRequestDTO reqDTO) {

        try {
            JobExecution jobExecution = jobLauncher.run(
                closeJobConfig.sndngCloseJob(),
                getJobParameters(reqDTO, ApiConstants.SndngProcessStatus.SEND_OK.getCode())
            );

            while(jobExecution.isRunning()){
                log.info("...");
            }
            printLog(jobExecution);

        } catch (JobExecutionAlreadyRunningException | JobInstanceAlreadyCompleteException
                 | JobParametersInvalidException | org.springframework.batch.core.repository.JobRestartException e) {

            log.error(e.getMessage());
        }
        return ApiResponseDTO.success(HttpStatus.OK);
    }

    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
        @Content(
            mediaType = "application/json",
            examples = {
                @ExampleObject(
                    name = "춘천",
                    value = CCN),
                @ExampleObject(
                    name = "천안시 동남구청",
                    value = CAN_1),
                @ExampleObject(
                    name = "천안시 서북구청",
                    value = CAN_2)
            })
    })
    @Operation(summary = "sendBulks", description = "sendBulks")
    @PostMapping(value = "/sendBulks", produces = MediaType.APPLICATION_JSON_VALUE)
    public IApiResponse sendBulks(@RequestBody final CmmEnsRequestDTO reqDTO) {

        try {
            JobExecution jobExecution = jobLauncher.run(
                sendBulksJobConfig.sndngSendBulksJob(),
                getJobParameters(reqDTO, ApiConstants.SndngProcessStatus.MAKE_OK.getCode())
            );

            while(jobExecution.isRunning()){
                log.info("...");
            }
            printLog(jobExecution);

        } catch (JobExecutionAlreadyRunningException | JobInstanceAlreadyCompleteException
                 | JobParametersInvalidException | org.springframework.batch.core.repository.JobRestartException e) {

            log.error(e.getMessage());
        }
        return ApiResponseDTO.success(HttpStatus.OK);
    }

    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
        @Content(
            mediaType = "application/json",
            examples = {
                @ExampleObject(
                    name = "춘천",
                    value = CCN),
                @ExampleObject(
                    name = "천안시 동남구청",
                    value = CAN_1),
                @ExampleObject(
                    name = "천안시 서북구청",
                    value = CAN_2)
            })
    })
    @Operation(summary = "statusBulks", description = "statusBulks")
    @PostMapping(value = "/statusBulks", produces = MediaType.APPLICATION_JSON_VALUE)
    public IApiResponse statusBulks(@RequestBody final CmmEnsRequestDTO reqDTO) {

        try {
            JobExecution jobExecution = jobLauncher.run(
                statusJobConfig.sndngStatusBulksJob(),
                getJobParameters(reqDTO, ApiConstants.SndngProcessStatus.SEND_OK.getCode())
            );

            while(jobExecution.isRunning()){
                log.info("...");
            }
            printLog(jobExecution);

        } catch (JobExecutionAlreadyRunningException | JobInstanceAlreadyCompleteException
                 | JobParametersInvalidException | org.springframework.batch.core.repository.JobRestartException e) {

            log.error(e.getMessage());
        }
        return ApiResponseDTO.success(HttpStatus.OK);
    }

    @io.swagger.v3.oas.annotations.parameters.RequestBody(required = true, content = {
        @Content(
            mediaType = "application/json",
            examples = {
                @ExampleObject(
                    name = "춘천",
                    value = CCN),
                @ExampleObject(
                    name = "천안시 동남구청",
                    value = CAN_1),
                @ExampleObject(
                    name = "천안시 서북구청",
                    value = CAN_2)
            })
    })
    @Operation(summary = "ktGbsAccessTokenUpdate", description = "ktGbsAccessTokenUpdate")
    @PostMapping(value = "/ktGbsAccessTokenUpdate", produces = MediaType.APPLICATION_JSON_VALUE)
    public IApiResponse tokenUpdateJobConfig(@RequestBody final CmmEnsRequestDTO reqDTO) {

        try {
            JobExecution jobExecution = jobLauncher.run(
                tokenUpdateJobConfig.ktGbsAccessTokenUpdateJob(),
                getJobParameters(reqDTO, "")
            );

            while(jobExecution.isRunning()){
                log.info("...");
            }
            printLog(jobExecution);

        } catch (JobExecutionAlreadyRunningException | JobInstanceAlreadyCompleteException
                 | JobParametersInvalidException | org.springframework.batch.core.repository.JobRestartException e) {

            log.error(e.getMessage());
        }
        return ApiResponseDTO.success(HttpStatus.OK);
    }

    private JobParameters getJobParameters(final CmmEnsRequestDTO reqDTO, final String processStatus){
        Map<String, JobParameter> confMap = new HashMap<>();

        confMap.put("signguCode", new JobParameter(reqDTO.getSignguCode()));
        confMap.put("ffnlgCode", new JobParameter(reqDTO.getFfnlgCode()));
        confMap.put("startDate", new JobParameter(new Date()));
        confMap.put("isSlackEnabled", new JobParameter(isSlackEnabled));
        if(Checks.isNotEmpty(processStatus)) confMap.put("sndngProcessSttus", new JobParameter(processStatus));
        return new JobParameters(confMap);
    }

    private static void printLog(JobExecution jobExecution) {
        log.info("Job Execution: " + jobExecution.getStatus());
        log.info("Job getJobConfigurationName: " + jobExecution.getJobConfigurationName());
        log.info("Job getJobId: " + jobExecution.getJobId());
        log.info("Job getExitStatus: " + jobExecution.getExitStatus());
        log.info("Job getJobInstance: " + jobExecution.getJobInstance());
        log.info("Job getStepExecutions: " + jobExecution.getStepExecutions());
        log.info("Job getLastUpdated: " + jobExecution.getLastUpdated());
        log.info("Job getFailureExceptions: " + jobExecution.getFailureExceptions());
    }
}
