package com.erp.task.monitor;

import com.erp.task.alert.AlertService;
import com.erp.task.entity.ScheduledTask;
import com.erp.task.repository.ScheduledTaskRepository;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 任务监控
 */
@Slf4j
@Component
public class TaskMonitor {

    private final MeterRegistry meterRegistry;
    private final ScheduledTaskRepository taskRepository;
    private final AlertService alertService;
    private final ScheduledTaskRepository scheduledTaskRepository;

    private final Map<Long, AtomicLong> taskExecutions = new ConcurrentHashMap<>();
    private final Map<Long, AtomicLong> taskSuccesses = new ConcurrentHashMap<>();
    private final Map<Long, AtomicLong> taskFailures = new ConcurrentHashMap<>();
    private final Map<Long, Timer> taskTimers = new ConcurrentHashMap<>();

    private Counter totalExecutions;
    private Counter totalSuccesses;
    private Counter totalFailures;
    private Timer executionTimer;

    public TaskMonitor(MeterRegistry meterRegistry,
                       ScheduledTaskRepository taskRepository,
                       AlertService alertService,
                       ScheduledTaskRepository scheduledTaskRepository) {
        this.meterRegistry = meterRegistry;
        this.taskRepository = taskRepository;
        this.alertService = alertService;
        this.scheduledTaskRepository = scheduledTaskRepository;
    }

    @PostConstruct
    public void init() {
        // 注册全局指标
        totalExecutions = Counter.builder("task.executions.total")
                .description("总执行次数")
                .register(meterRegistry);

        totalSuccesses = Counter.builder("task.executions.success")
                .description("成功次数")
                .register(meterRegistry);

        totalFailures = Counter.builder("task.executions.failure")
                .description("失败次数")
                .register(meterRegistry);

        executionTimer = Timer.builder("task.execution.duration")
                .description("任务执行耗时")
                .register(meterRegistry);

        // 注册任务数指标
        Gauge.builder("task.running.count", taskRepository, repo ->
                repo.findAllRunning().size())
                .description("运行中的任务数")
                .register(meterRegistry);
    }

    /**
     * 记录任务执行
     */
    public void recordExecution(Long taskId) {
        totalExecutions.increment();

        AtomicLong counter = taskExecutions.computeIfAbsent(taskId, k -> {
            Counter c = Counter.builder("task.executions")
                    .tag("task_id", String.valueOf(taskId))
                    .description("任务执行次数")
                    .register(meterRegistry);
            return new AtomicLong(0);
        });
        counter.incrementAndGet();
    }

    /**
     * 记录任务成功
     */
    public void recordSuccess(Long taskId) {
        totalSuccesses.increment();

        AtomicLong counter = taskSuccesses.computeIfAbsent(taskId, k -> {
            Counter c = Counter.builder("task.success")
                    .tag("task_id", String.valueOf(taskId))
                    .description("任务成功次数")
                    .register(meterRegistry);
            return new AtomicLong(0);
        });
        counter.incrementAndGet();
    }

    /**
     * 记录任务失败
     */
    public void recordFailure(Long taskId) {
        totalFailures.increment();

        AtomicLong counter = taskFailures.computeIfAbsent(taskId, k -> {
            Counter c = Counter.builder("task.failure")
                    .tag("task_id", String.valueOf(taskId))
                    .description("任务失败次数")
                    .register(meterRegistry);
            return new AtomicLong(0);
        });
        counter.incrementAndGet();
    }

    /**
     * 记录执行耗时
     */
    public void recordDuration(Long taskId, long durationMs) {
        executionTimer.record(durationMs, TimeUnit.MILLISECONDS);

        Timer timer = taskTimers.computeIfAbsent(taskId, k ->
                Timer.builder("task.duration")
                        .tag("task_id", String.valueOf(taskId))
                        .description("任务执行耗时")
                        .register(meterRegistry));
        timer.record(durationMs, TimeUnit.MILLISECONDS);
    }

    /**
     * 任务失败时触发告警
     */
    public void alertOnFailure(ScheduledTask task, String errorMessage) {
        if (task.getAlertEnabled() != null && task.getAlertEnabled()) {
            alertService.sendAlert(task, errorMessage);
        }
    }

    /**
     * 获取任务执行统计
     */
    public Map<String, Object> getTaskStats(Long taskId) {
        AtomicLong executions = taskExecutions.get(taskId);
        AtomicLong successes = taskSuccesses.get(taskId);
        AtomicLong failures = taskFailures.get(taskId);
        Timer timer = taskTimers.get(taskId);

        Map<String, Object> stats = new ConcurrentHashMap<>();
        stats.put("taskId", taskId);
        stats.put("totalExecutions", executions != null ? executions.get() : 0);
        stats.put("totalSuccesses", successes != null ? successes.get() : 0);
        stats.put("totalFailures", failures != null ? failures.get() : 0);
        stats.put("avgDuration", timer != null ? timer.mean(TimeUnit.MILLISECONDS) : 0);
        stats.put("maxDuration", timer != null ? timer.max(TimeUnit.MILLISECONDS) : 0);

        return stats;
    }

    /**
     * 获取健康状态
     */
    public boolean isHealthy() {
        // 如果失败率超过10%，认为不健康
        double total = totalExecutions.count();
        if (total == 0) return true;

        double failures = totalFailures.count();
        return (failures / total) < 0.1;
    }
}
