package com.moka.gdtauto.service;

import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.moka.gdtauto.GdtAutoApplication;
import com.moka.gdtauto.client.TencentAdsApiClientFactory;
import com.moka.gdtauto.common.Constant;
import com.moka.gdtauto.entity.AdPlan;
import com.moka.gdtauto.entity.AdPlanConf;
import com.moka.gdtauto.util.TargetConfUtil;
import com.tencent.ads.model.v3.WriteTargetingSetting;
import com.tencent.ads.v3.TencentAds;

import lombok.extern.slf4j.Slf4j;

/**
 * mvn test -Dtest=AdPlanServiceTest#testUpdateTargetting -Dspring.profiles.active=test
 */

@Slf4j
@SpringBootTest(classes = GdtAutoApplication.class)
@ActiveProfiles("test")
class AdPlanServiceTest {

    @Autowired
    private AdPlanService adPlanService;
    @Autowired
    private AdPlanConfService adPlanConfService;
    @Autowired
    private TencentAdsApiClientFactory clientFactory;

    @Test
    public void testUpdateTargetting() {
        // 获取所有广告计划配置
        List<AdPlanConf> confList = adPlanConfService.list(
            new LambdaQueryWrapper<AdPlanConf>()
                .in(AdPlanConf::getAccountGroupId, List.of(5,18))
                .eq(AdPlanConf::getDeleted, 0));
        log.info("查询到 {} 个广告计划配置", confList.size());

        if (confList.isEmpty()) {
            log.warn("没有可用的广告计划配置");
            return;
        }

        // 使用 Semaphore 控制并发数为 10
        Semaphore semaphore = new Semaphore(10);

        // 使用虚拟线程池进行并发处理
        try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
            for (AdPlanConf conf : confList) {
                executor.submit(() -> {
                    try {
                        semaphore.acquire();
                        processAdPlanConf(conf);
                    } catch (InterruptedException e) {
                        log.error("获取信号量被中断", e);
                        Thread.currentThread().interrupt();
                    } finally {
                        semaphore.release();
                    }
                });
            }
            // 关闭线程池并等待所有任务完成
            executor.shutdown();
            boolean terminated = executor.awaitTermination(30, TimeUnit.MINUTES);
            if (!terminated) {
                log.warn("部分任务未在指定时间内完成");
            }
        } catch (InterruptedException e) {
            log.error("并发处理被中断", e);
            Thread.currentThread().interrupt();
        }

        log.info("所有广告计划定向更新完成");
    }

    /**
     * 处理单个 AdPlanConf 下的所有 AdPlan
     */
    private void processAdPlanConf(AdPlanConf conf) {
        try {
            log.info("开始处理配置 ID: {}, 名称: {}", conf.getId(), conf.getName());
            TencentAds tencentAds = clientFactory.getTencentAds("12329", Constant.MAIN_ORG_ACCOUNT_ID);
            // 查询该配置下所有 adgroupId > 0 的广告计划
            List<AdPlan> plans = adPlanService.lambdaQuery()
                    .eq(AdPlan::getAdPlanConfId, conf.getId())
                    .gt(AdPlan::getAdgroupId, 0)
                    .eq(AdPlan::getDeleted, 0)
                    .list();

            if (plans.isEmpty()) {
                log.info("配置 ID: {} 下没有有效的广告计划", conf.getId());
                return;
            }

            log.info("配置 ID: {} 下找到 {} 个广告计划", conf.getId(), plans.size());

            // 获取定向设置 (使用 targeting ID = 2)
            WriteTargetingSetting targeting = TargetConfUtil.getTargetingSetting(2);
            if (targeting == null) {
                log.error("无法获取定向设置 ID=2");
                return;
            }

            // 为每个计划更新定向
            for (AdPlan plan : plans) {
                try {
                    adPlanService.updateAdgroupTargeting(tencentAds, conf, plan, targeting);
                    log.info("更新定向成功 - 配置ID: {}, 计划ID: {}, adgroupId: {}",
                            conf.getId(), plan.getId(), plan.getAdgroupId());
                } catch (Exception e) {
                    log.error("更新定向失败 - 配置ID: {}, 计划ID: {}, adgroupId: {}",
                            conf.getId(), plan.getId(), plan.getAdgroupId(), e);
                }
            }

            log.info("配置 ID: {} 处理完成", conf.getId());
        } catch (Exception e) {
            log.error("处理配置 ID: {} 时发生错误", conf.getId(), e);
        }
    }
}
