package com.eactive.ext.kjb.ums;

import com.eactive.apim.portal.portaluser.entity.PortalUser;
import com.eactive.apim.portal.template.entity.MessageRequest;
import com.eactive.apim.portal.template.repository.MessageRequestRepository;
import com.eactive.ext.kjb.common.KjbEaiBatchException;
import com.eactive.ext.kjb.common.KjbProperty;
import com.eactive.ext.kjb.eai.EaiBatchInterface;
import com.eactive.ext.kjb.eai.EaiBatchMessage;
import com.eactive.ext.kjb.eai.KjbEaiBatchModule;
//import com.eactive.ext.kjb.safedb.KjbSafedbWrapper;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import javax.transaction.Transactional;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class EmailJob {
    private final KjbProperty prop;
    private final MessageRequest messageRequest;

    private static final int READY = 1; // Temp 파일 생성 단계
    private static final int BEFORE_SEND = 2;
    private static final int SEND = 3;

    private final Path eaiFilePath;
    private final Path backupFilePath;
    private final Path failedFilePath;
    private final MessageRequestRepository messageRequestRepository;
    private final LocalDateTime now = LocalDateTime.now();

    private int eaiPhase = 0;



    private EmailJob(KjbProperty prop, MessageRequest messageRequest, MessageRequestRepository messageRequestRepository) {
        this.messageRequest = messageRequest;
        this.prop = prop;

//        String filename = messageRequest.getServiceId() + "_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(now) + ".dat";
        String filename = messageRequest.getServiceId() + "_" + DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS").format(now) + ".dat";
        this.eaiFilePath = Paths.get(prop.getUmsEaiBatchSendDir(), filename);
        this.backupFilePath = Paths.get(prop.getUmsEaiBatchBackupDir(), filename);
        this.failedFilePath = Paths.get(prop.getUmsEaiBatchBackupDir(), filename + ".failed");

        this.messageRequestRepository = messageRequestRepository;

        this.doCreateNewFile();
    }


    public static EmailJob create(KjbProperty prop, MessageRequest messageRequest, MessageRequestRepository repository) {
        if (prop == null) {
            throw new IllegalArgumentException("Property is null");
        }
        if (messageRequest == null) {
            throw new IllegalArgumentException("MessageRequest is null");
        }

        validateMessageRequest(messageRequest, false, true);

        if (messageRequest.getUser() != null) {
            PortalUser user = messageRequest.getUser();
//            messageRequest.setUmsUid(UUIDBase62Util.uuidStringToBase62(user.getId()));
            messageRequest.setUmsUid(user.getId());

            if (repository != null) {
                repository.save(messageRequest);
            }
        }

        return new EmailJob(prop, messageRequest, repository);
    }

    public static EmailValidationResult validateMessageRequest(MessageRequest messageRequest, boolean forSend, boolean isThrow) {
        Map<String, String> errors = new HashMap<>();


        if (StringUtils.isEmpty(messageRequest.getId())) {
            errors.put("id", "ID is required");
        }

        if (forSend) {
            if (StringUtils.isEmpty(messageRequest.getEmail())) {
                errors.put("email", "Email is required");
            }

            if (StringUtils.isEmpty(messageRequest.getUsername())) {
                errors.put("username", "Username is required");
            }

            if (StringUtils.isEmpty(messageRequest.getServiceId())) {
                errors.put("serviceId", "Service ID is required");
            }
        }


        // 결과 리턴
        if (!errors.isEmpty()) {
            if (isThrow) {
                throw new IllegalArgumentException("Invalid MessageRequest: " + errors);
            } else {
                return EmailValidationResult.failed(errors);
            }
        }

        return EmailValidationResult.ok();
    }


    @Transactional
    public void sendEmail() throws KjbEaiBatchException {
        if (messageRequestRepository != null) {
            PortalUser user = messageRequest.getUser();
            if (user != null) {
                // messageRequest.setUmsUid(UUIDBase62Util.uuidStringToBase62(user.getId()));
                messageRequest.setUmsUid(user.getId());
            }

            messageRequestRepository.save(messageRequest);
        }
        try {
            log.debug("이메일 파일 생성");
            doSaveFile();

            log.debug("EAI 배치 호출");
            eaiBatchCall();

            log.debug("발송 성공 처리");
            doSuccess();
        } catch (KjbEaiBatchException e) {
            doFail(e);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            doFail(e);
        } finally {
            doDeleteEaiFile();
        }
    }

    private void doDeleteEaiFile() {
        // TODO: EAI 발송용 파일 삭제
    }

    private void doFail(Exception e) throws KjbEaiBatchException {
        // TODO: EAI 발송 실패 처리
        if (e instanceof KjbEaiBatchException) {
            throw (KjbEaiBatchException) e;
        } else {
            throw new KjbEaiBatchException("이메일 발송 실패", e);
        }
    }

    private void eaiBatchCall() throws KjbEaiBatchException {
        KjbEaiBatchModule eaiBatchModule = new KjbEaiBatchModule(prop);
        EaiBatchInterface eaiBatchInterface = EaiBatchInterface.builder()
                .id(prop.getUmsEaiBatchInterfaceId())
                .sendDir(prop.getUmsEaiBatchSendDir())
                .backupDir(prop.getUmsEaiBatchBackupDir())
                .errorDir(prop.getUmsEaiBatchErrorDir())
                .build();
        EaiBatchMessage result = eaiBatchModule.call(eaiBatchInterface, eaiFilePath.getFileName().toString());

        if (!"1".equals(result.getResultCode())) {
            log.error("EAI Batch call failed: {}", result);
            throw new IllegalStateException("EAI Batch call failed: " + result);
        }

        log.debug("EAI Batch call result: {}", result);
    }

    private void doSuccess() {
        // 딱히 뭐 할 거 없음.
    }


    public void doCreateNewFile() {
        if (eaiFilePath.toFile().exists()) {
            log.error("Mail File exists for ID: {}", messageRequest.getId());
            throw new IllegalStateException("Mail File exists for ID: " + messageRequest.getId());
        }

        File mailFile = eaiFilePath.toFile();
        try {
            boolean created = mailFile.createNewFile();
            if (!created) {
                log.error("Cannot create mail file for ID: {}", messageRequest.getId());
                throw new IllegalStateException("Cannot create mail file for ID: " + messageRequest.getId());
            }
        } catch (Exception ex) {
            log.error("Cannot create mail file for ID: {}", messageRequest.getId(), ex);
            throw new IllegalStateException("Cannot create mail file for ID: " + messageRequest.getId(), ex);
        }
    }

    public void doSaveFile() {
        String jsonContent = generateJSON(true);
        log.debug("Generated JSON: \n{}", jsonContent);

        // 저장은 임시 파일에 euc-kr 인코딩으로 저장
        byte[] data = null;
        try {
            data = jsonContent.getBytes("euc-kr");
        } catch (UnsupportedEncodingException e) {
            log.error("Cannot encode(euc-kr) JSON: \n{}", jsonContent, e);
            throw new RuntimeException(e);
        }
        try {
            Files.write(eaiFilePath, data);
            log.debug("Wrote JSON to file: {}", eaiFilePath.toString());
        } catch (IOException e) {
            log.error("Cannot write JSON to file: {}", eaiFilePath.toString(), e);
            throw new RuntimeException(e);
        }
    }

    public String generateJSON(boolean isPretty) {
        validateMessageRequest(messageRequest, true, true);
//        KjbSafedbWrapper safedb = KjbSafedbWrapper.getInstance();

        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("MAKE_DATE", DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDateTime.now()));
        jsonObject.addProperty("MAKE_SEQNO", DateTimeFormatter.ofPattern("HHmmssSSS").format(LocalDateTime.now()));
        jsonObject.addProperty("CAMP_ID", messageRequest.getServiceId()); // 전자금융 고객이메일 발송 업무ID (SERVICE_ID)
        jsonObject.addProperty("ID", messageRequest.getUmsUid()); // 고객 ID
//        jsonObject.addProperty("EMAIL", safedb.encryptNotRnnoString(messageRequest.getEmail()));
        jsonObject.addProperty("EMAIL", messageRequest.getEmail());
        jsonObject.addProperty("NAME", messageRequest.getUsername());
        jsonObject.addProperty("ENCKEY", ""); // 보안메일용으로 기입 불필요

        Gson gson = new Gson();
        String message = messageRequest.getMessage();
        JsonArray jsonArray = new JsonArray();
        log.debug("Template string to json: {}", message);
        if (StringUtils.isNotEmpty(message)) {
            JsonObject contentJSon = gson.fromJson(message, JsonObject.class);
            contentJSon.entrySet().forEach(entry -> {
                jsonObject.add(entry.getKey(), entry.getValue());
            });
        }

        jsonArray.add(jsonObject);

//        jsonObject.addProperty("SUBJECT", messageRequest.getSubject());
//        jsonObject.addProperty("MESSAGE", messageRequest.getMessage());

        String jsonString;
        if (isPretty) {
            // pretty print 제외
//            jsonString = new GsonBuilder().setPrettyPrinting().create().toJson(jsonArray);
            jsonString = new GsonBuilder().create().toJson(jsonArray);
        } else {
            jsonString = jsonObject.toString();
        }

        return jsonString;
    }
}
