package com.caliverse.admin.scheduler;

import com.caliverse.admin.domain.entity.log.LogAction;
import com.caliverse.admin.domain.entity.log.LogStatus;
import com.caliverse.admin.global.component.manager.BusinessProcessIdManager;
import com.caliverse.admin.mongodb.service.BusinessLogService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Map;

@Slf4j
public abstract class CommonScheduler implements Scheduler {

    protected final BusinessLogService businessLogService;
    protected final BusinessProcessIdManager processIdManager;

    protected CommonScheduler(BusinessLogService businessLogService, BusinessProcessIdManager processIdManager) {
        this.businessLogService = businessLogService;
        this.processIdManager = processIdManager;
    }

    @Override
    public void execute() {
        LocalDateTime startTime = LocalDateTime.now();
        String schedulerName = getSchedulerType().name();

        try {
            log.info("Start executing scheduler: {}", schedulerName);

            executeInternal();

            log.info("Finished executing scheduler: {}", schedulerName);
        } catch (Exception e) {
            businessLogService.logScheduler(
                    LogStatus.FAILURE,
                    String.format("Scheduler %s failed: %s", schedulerName, e.getMessage()),
                    schedulerName,
                    startTime,
                    LocalDateTime.now(),
                    Map.of("error", e.getMessage(), "stackTrace", Arrays.toString(e.getStackTrace()))
            );
            log.error("Error executing scheduler {}: {}", schedulerName, e.getMessage(), e);
        }
    }

    /**
     * 스케줄러 구현체에서 실제 작업을 수행하는 메소드
     */
    protected abstract void executeInternal();

    protected void executeWithProcessId(LogAction action, Runnable businessLogic) {
        processIdManager.createNewProcessId();
        processIdManager.setCurrentAction(action);

        try {
            businessLogic.run();
        } finally {
            processIdManager.clear();
        }
    }
}
