package org.hzhub.workflow.task;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.hzhub.common.tenant.core.TenantEntity;
import org.hzhub.common.tenant.helper.TenantHelper;
import org.hzhub.system.domain.SysTenant;
import org.hzhub.system.mapper.SysTenantMapper;
import org.hzhub.system.service.ISysConfigService;
import org.hzhub.workflow.service.IWecomApprovalService;
import org.hzhub.workflow.service.IWecomTenantConfigService;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 企业微信审批同步定时任务（动态调度，多租户独立）
 * <p>支持运行时启动/停止/修改频率，配置存储在 sys_config 表中</p>
 * <p>每个租户独立执行，未配置企业微信的租户自动跳过</p>
 *
 * @author hzhub
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class WecomApprovalSyncTask {

    private static final String CRON_CONFIG_KEY = "wecom.approval.sync.cron";
    private static final String ENABLED_CONFIG_KEY = "wecom.approval.sync.enabled";

    private final IWecomApprovalService wecomApprovalService;
    private final ISysConfigService configService;
    private final IWecomTenantConfigService tenantConfigService;
    private final SysTenantMapper tenantMapper;
    private final TaskScheduler taskScheduler;

    private volatile ScheduledFuture<?> scheduledFuture;

    /**
     * 应用启动完成后，如果配置为启用则自动启动定时任务
     */
    @EventListener(ApplicationReadyEvent.class)
    public void init() {
        try {
            String enabled = configService.selectConfigByKey(ENABLED_CONFIG_KEY);
            if ("true".equals(enabled)) {
                start();
            }
        } catch (Exception e) {
            log.warn("初始化审批同步定时任务失败: {}", e.getMessage());
        }
    }

    /**
     * 启动定时任务
     */
    public synchronized void start() {
        if (scheduledFuture != null && !scheduledFuture.isCancelled()) {
            log.info("审批同步定时任务已在运行中");
            return;
        }

        String cron = configService.selectConfigByKey(CRON_CONFIG_KEY);
        if (cron == null || cron.isBlank()) {
            cron = "0 0/5 * * * ?";
        }

        log.info("启动审批同步定时任务, cron: {}", cron);
        scheduledFuture = taskScheduler.schedule(() -> {
            try {
                log.info("[定时任务] 开始执行企业微信审批增量同步（多租户）");
                syncAllTenants();
                log.info("[定时任务] 审批增量同步全部完成");
            } catch (Exception e) {
                log.error("[定时任务] 审批增量同步异常", e);
            }
        }, new CronTrigger(cron));

        configService.updateConfigByKey(ENABLED_CONFIG_KEY, "true");
    }

    /**
     * 停止定时任务
     */
    public synchronized void stop() {
        if (scheduledFuture == null) {
            log.info("审批同步定时任务未启动");
            return;
        }

        log.info("停止审批同步定时任务");
        scheduledFuture.cancel(false);
        scheduledFuture = null;
        configService.updateConfigByKey(ENABLED_CONFIG_KEY, "false");
    }

    /**
     * 检查是否正在运行
     */
    public boolean isRunning() {
        return scheduledFuture != null && !scheduledFuture.isCancelled();
    }

    /**
     * 获取当前 cron 表达式
     */
    public String getCurrentCron() {
        return configService.selectConfigByKey(CRON_CONFIG_KEY);
    }

    /**
     * 设置 cron 表达式
     */
    public synchronized void setCron(String cron) {
        configService.updateConfigByKey(CRON_CONFIG_KEY, cron);
        // 如果正在运行，重启以应用新 cron
        if (isRunning()) {
            stop();
            start();
        }
    }

    /**
     * 遍历所有租户，依次执行增量同步
     */
    private void syncAllTenants() {
        List<SysTenant> tenants = tenantMapper.selectList(
            new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<SysTenant>()
                .eq(SysTenant::getStatus, "0")
        );

        log.info("共发现 {} 个有效租户，开始逐个执行增量同步", tenants.size());

        AtomicInteger successCount = new AtomicInteger(0);
        AtomicInteger skipCount = new AtomicInteger(0);
        AtomicInteger errorCount = new AtomicInteger(0);

        for (SysTenant tenant : tenants) {
            final String tenantId = tenant.getTenantId();
            try {
                TenantHelper.dynamic(tenantId, () -> {
                    var config = tenantConfigService.getByCurrentTenant();
                    if (config == null || !"1".equals(config.getEnabled())) {
                        log.info("租户[{}]未配置或未启用企业微信，跳过同步", tenantId);
                        skipCount.incrementAndGet();
                        return;
                    }
                    log.info("租户[{}]开始增量同步（近1天）", tenantId);
                    try {
                        String result = wecomApprovalService.incrementalSync(1);
                        log.info("租户[{}]同步结果: {}", tenantId, result);
                        successCount.incrementAndGet();
                    } catch (Exception e) {
                        log.error("租户[{}]增量同步失败: {}", tenantId, e.getMessage(), e);
                        errorCount.incrementAndGet();
                    }
                });
            } catch (Exception e) {
                log.error("切换租户[{}]上下文失败", tenantId, e);
                errorCount.incrementAndGet();
            }
        }

        log.info("[定时任务] 多租户增量同步完成: 成功={}, 跳过={}, 失败={}", successCount.get(), skipCount.get(), errorCount.get());
    }
}
