package com.caliverse.admin.scheduler;

import com.caliverse.admin.domain.entity.HISTORYTYPEDETAIL;
import com.caliverse.admin.domain.entity.InGame;
import com.caliverse.admin.domain.entity.Mail;
import com.caliverse.admin.domain.entity.log.LogAction;
import com.caliverse.admin.domain.entity.log.LogCategory;
import com.caliverse.admin.domain.entity.log.LogStatus;
import com.caliverse.admin.global.common.annotation.BusinessProcess;
import com.caliverse.admin.global.common.utils.CommonUtils;
import com.caliverse.admin.global.component.manager.BusinessProcessIdManager;
import com.caliverse.admin.mongodb.domain.*;
import com.caliverse.admin.mongodb.entity.DBType;
import com.caliverse.admin.mongodb.repository.DynamodbHistoryLogRepository;
import com.caliverse.admin.mongodb.service.BusinessLogService;
import com.caliverse.admin.mongodb.service.OldHistoryLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledFuture;

@Service
@Slf4j
public class MigrationService {
    private final OldHistoryLogService oldHistoryLogService;
    private final BusinessLogService businessLogService;
    private final BusinessProcessIdManager processIdManager;
    @Autowired
    private DynamodbHistoryLogRepository dynamodbHistoryLogRepository;

    public MigrationService(OldHistoryLogService oldHistoryLogService, BusinessLogService businessLogService, BusinessProcessIdManager processIdManager) {
        this.oldHistoryLogService = oldHistoryLogService;
        this.businessLogService = businessLogService;
        this.processIdManager = processIdManager;
    }

    @BusinessProcess(action = LogAction.UNKNOWN)
    public void migrationHistory() {
        List<DynamodbHistoryLogInfo> dynamodbHistoryLogInfos = oldHistoryLogService.loadHistoryData(DBType.DYNAMODB, DynamodbHistoryLogInfo.class);

        dynamodbHistoryLogInfos.forEach(history -> {
            LogAction action = getLogAction(history.getHistoryType());

            DynamodbDomain domain = DynamodbDomain.builder()
                    .tranId(history.getTranId())
                    .tableName(history.getTableName())
                    .operationType(history.getOperationType())
                    .changed(history.getChanged())
                    .data(history.getData())
                    .build();

            CompletableFuture<String> logFuture = businessLogService.saveLog(
                    LogCategory.DYNAMODB,
                    LogStatus.SUCCESS,
                    history.getTimestampAsLocalDateTime(),
                    "",
                    domain,
                    history.getUserId(),
                    history.getUserIP(),
                    processIdManager.getCurrentProcessId(),
                    action
            );

            logFuture.whenComplete((result, throwable) -> {
                if (throwable == null) {
                    try {
                        dynamodbHistoryLogRepository.deleteById(history.getId());
                        log.debug("DynamoDB 히스토리 마이그레이션 및 삭제 완료: tranId={}", history.getTranId());
                    } catch (Exception e) {
                        log.error("DynamoDB 히스토리 삭제 실패: tranId={}, error={}", history.getTranId(), e.getMessage());
                    }
                } else {
                    log.error("DynamoDB 히스토리 마이그레이션 실패: tranId={}", history.getTranId());
                }
            });
        });

        List<MysqlHistoryLogInfo> mysqlHistoryLogInfos = oldHistoryLogService.loadHistoryData(DBType.MYSQL, MysqlHistoryLogInfo.class);
        mysqlHistoryLogInfos.forEach(history -> {
            LogAction action = getLogAction(history.getHistoryType());

            MariadbDomain domain = MariadbDomain.builder()
                    .tranId(history.getTranId())
                    .tableName(history.getTableName())
                    .operationType(history.getOperationType())
                    .changed(history.getChanged())
                    .data(history.getData())
                    .build();

            CompletableFuture<String> logFuture = businessLogService.saveLog(
                    LogCategory.DYNAMODB,
                    LogStatus.SUCCESS,
                    history.getTimestampAsLocalDateTime(),
                    "",
                    domain,
                    history.getUserId(),
                    history.getUserIP(),
                    processIdManager.getCurrentProcessId(),
                    action
            );

            logFuture.whenComplete((result, throwable) -> {
                if (throwable == null) {
                    try {
                        dynamodbHistoryLogRepository.deleteById(history.getId());
                        log.debug("Mysql 히스토리 마이그레이션 및 삭제 완료: tranId={}", history.getTranId());
                    } catch (Exception e) {
                        log.error("Mysql 히스토리 삭제 실패: tranId={}, error={}", history.getTranId(), e.getMessage());
                    }
                } else {
                    log.error("Mysql 히스토리 마이그레이션 실패: tranId={}", history.getTranId());
                }
            });
        });
    }

    private LogAction getLogAction(HISTORYTYPEDETAIL historyType) {
        if(historyType.equals(HISTORYTYPEDETAIL.NOTICE_ADD)){
            return LogAction.NOTICE;
        }else if(historyType.equals(HISTORYTYPEDETAIL.BATTLE_EVENT_ADD) || historyType.equals(HISTORYTYPEDETAIL.BATTLE_EVENT_UPDATE)){
            return LogAction.BATTLE_EVENT;
        }else if(historyType.equals(HISTORYTYPEDETAIL.EVENT_ADD) || historyType.equals(HISTORYTYPEDETAIL.EVENT_UPDATE)
                || historyType.equals(HISTORYTYPEDETAIL.EVENT_DELETE) || historyType.equals(HISTORYTYPEDETAIL.SYSTEM_META_MAIL_DELETE)){
            return LogAction.EVENT;
        }else if(historyType.equals(HISTORYTYPEDETAIL.MAIL_ADD) || historyType.equals(HISTORYTYPEDETAIL.MAIL_DELETE) || historyType.equals(HISTORYTYPEDETAIL.MAIL_UPDATE)){
            return LogAction.MAIL;
        }else if(historyType.equals(HISTORYTYPEDETAIL.ITEM_DELETE) || historyType.equals(HISTORYTYPEDETAIL.ITEM_UPDATE)){
            return  LogAction.ITEM;
        }else if(historyType.equals(HISTORYTYPEDETAIL.LAND_OWNER_CHANGE_ADD) || historyType.equals(HISTORYTYPEDETAIL.LAND_OWNER_CHANGE_MAIL)){
            return LogAction.LAND_OWNER_CHANGE;
        }else if(historyType.equals(HISTORYTYPEDETAIL.NICKNAME_REGISTRY_ADD) || historyType.equals(HISTORYTYPEDETAIL.NICKNAME_REGISTRY_DELETE) || historyType.equals(HISTORYTYPEDETAIL.NICKNAME_UPDATE)){
            return LogAction.NICKNAME_CHANGE;
        }else if(historyType.equals(HISTORYTYPEDETAIL.LAND_DESC_INITIALIZE)){
            return LogAction.DATA_INIT;
        }else if(historyType.equals(HISTORYTYPEDETAIL.MENU_BANNER_ADD) || historyType.equals(HISTORYTYPEDETAIL.MENU_BANNER_UPDATE)){
            return LogAction.BANNER;
        }
        return LogAction.UNKNOWN;
    }
}
