package com.moka.gdtauto.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.moka.gdtauto.client.TencentAdsApiClientFactory;
import com.moka.gdtauto.common.Constant;
import com.moka.gdtauto.entity.AdPlanCreative;
import com.moka.gdtauto.mapper.AdPlanCreativeMapper;
import com.moka.gdtauto.service.AdPlanCreativeService;
import com.moka.gdtauto.service.AdPlanService;
import com.tencent.ads.model.v3.DynamicCreativesGetResponseData;
import com.tencent.ads.model.v3.FilterOperator;
import com.tencent.ads.model.v3.FilteringStruct;
import com.tencent.ads.v3.TencentAds;

import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 广告计划创意服务实现类
 * 
 * @author moka
 * @since 2026-02-24
 */
@Slf4j
@Service
@AllArgsConstructor
public class AdPlanCreativeServiceImpl extends ServiceImpl<AdPlanCreativeMapper, AdPlanCreative> implements AdPlanCreativeService {

    private final AdPlanCreativeMapper adPlanCreativeMapper;
    private final TencentAdsApiClientFactory clientFactory;
    private final AdPlanService adPlanService;
    
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createAdPlanCreative(AdPlanCreative adPlanCreative) {
        adPlanCreative.setCreateTime(LocalDateTime.now());
        adPlanCreative.setUpdateTime(LocalDateTime.now());
        adPlanCreative.setDeleted(0);
        if (adPlanCreative.getStatus() == null) {
            adPlanCreative.setStatus(1); // 默认待执行
        }
        
        this.save(adPlanCreative);
        log.info("创建广告计划创意成功，创意ID: {}, 创意名称: {}", adPlanCreative.getId(), adPlanCreative.getCreativeName());
        
        return adPlanCreative.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean batchCreateAdPlanCreatives(List<AdPlanCreative> adPlanCreatives) {
        if (adPlanCreatives == null || adPlanCreatives.isEmpty()) {
            log.warn("批量创建广告计划创意失败，创意列表为空");
            return false;
        }
        
        LocalDateTime now = LocalDateTime.now();
        for (AdPlanCreative creative : adPlanCreatives) {
            creative.setCreateTime(now);
            creative.setUpdateTime(now);
            creative.setDeleted(0);
            if (creative.getStatus() == null) {
                creative.setStatus(1); // 默认待执行
            }
        }
        
        boolean result = this.saveBatch(adPlanCreatives);
        log.info("批量创建广告计划创意成功，数量: {}", adPlanCreatives.size());
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAdPlanCreative(AdPlanCreative adPlanCreative) {
        AdPlanCreative existingCreative = this.getById(adPlanCreative.getId());
        
        if (existingCreative == null || existingCreative.getDeleted() == 1) {
            log.warn("广告计划创意不存在，创意ID: {}", adPlanCreative.getId());
            return false;
        }
        
        adPlanCreative.setUpdateTime(LocalDateTime.now());
        boolean result = this.updateById(adPlanCreative);
        log.info("更新广告计划创意成功，创意ID: {}", adPlanCreative.getId());
        
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteAdPlanCreative(Long creativeId) {
        AdPlanCreative existingCreative = this.getById(creativeId);
        
        if (existingCreative == null || existingCreative.getDeleted() == 1) {
            log.warn("广告计划创意不存在，创意ID: {}", creativeId);
            return false;
        }
        
        existingCreative.setDeleted(1);
        existingCreative.setUpdateTime(LocalDateTime.now());
        boolean result = this.updateById(existingCreative);
        
        log.info("删除广告计划创意成功，创意ID: {}", creativeId);
        return result;
    }

    @Override
    public List<AdPlanCreative> getCreativesByPlanId(Long planId) {
        return this.list(new LambdaQueryWrapper<AdPlanCreative>()
                .eq(AdPlanCreative::getAdPlanId, planId)
                .eq(AdPlanCreative::getDeleted, 0)
                .orderByDesc(AdPlanCreative::getCreateTime));
    }

    @Override
    public Page<AdPlanCreative> getAdPlanCreatives(Long planId, Integer status, Integer pageNum, Integer pageSize) {
        Page<AdPlanCreative> page = new Page<>(pageNum, pageSize);
        
        LambdaQueryWrapper<AdPlanCreative> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AdPlanCreative::getDeleted, 0);
        
        if (planId != null) {
            queryWrapper.eq(AdPlanCreative::getAdPlanId, planId);
        }
        if (status != null) {
            queryWrapper.eq(AdPlanCreative::getStatus, status);
        }
        
        queryWrapper.orderByDesc(AdPlanCreative::getCreateTime);
        
        return this.page(page, queryWrapper);
    }

    @Override
    public AdPlanCreative getAdPlanCreativeById(Long creativeId) {
        return this.getOne(new LambdaQueryWrapper<AdPlanCreative>()
                .eq(AdPlanCreative::getId, creativeId)
                .eq(AdPlanCreative::getDeleted, 0));
    }

    @Override
    public List<AdPlanCreative> getCreativesByConfId(Long confId) {
        return this.list(new LambdaQueryWrapper<AdPlanCreative>()
                .eq(AdPlanCreative::getAdPlanConfId, confId)
                .eq(AdPlanCreative::getDeleted, 0)
                .orderByAsc(AdPlanCreative::getId));
    }

    @Override
    public void adPlanCreativeStatus(Long confId) {
        final int PAGE_SIZE = 500;
        final int BATCH_LIMIT = 100; // 腾讯广告 adgroup_id IN 最大 100

        log.info("[定时任务] 开始同步广告创意 system_status");
        int totalUpdated = 0;
        try {
            // 获取 TencentAds 实例（使用主 orgAccountId）
            TencentAds tencentAds = clientFactory.getTencentAds(null, Constant.MAIN_ORG_ACCOUNT_ID);
            int pageNum = 1;
            while (true) {
                // 1. 分页查询 status=4 的广告创意，ID 降序
                LambdaQueryWrapper<AdPlanCreative> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(confId != null, AdPlanCreative::getAdPlanConfId, confId);
                queryWrapper.eq(AdPlanCreative::getDeleted, 0);
                queryWrapper.eq(AdPlanCreative::getStatus, 4);
                queryWrapper.orderByDesc(AdPlanCreative::getId);
                Page<AdPlanCreative> page = this.page(new Page<>(pageNum, PAGE_SIZE), queryWrapper);
                List<AdPlanCreative> records = page.getRecords();
                if (records == null || records.isEmpty()) {
                    break;
                }

                // 2. 按 accountId 分组
                Map<Long, List<AdPlanCreative>> groupByAccount = records.stream()
                        .filter(p -> p.getAdgroupId() != null && p.getAccountId() != null)
                        .collect(Collectors.groupingBy(AdPlanCreative::getAccountId));

                for (Map.Entry<Long, List<AdPlanCreative>> entry : groupByAccount.entrySet()) {
                    Long accountId = entry.getKey();
                    List<AdPlanCreative> plansOfAccount = entry.getValue();

                    // 3. 每组按 100 条分批调用 API
                    int batchCount = (int) Math.ceil((double) plansOfAccount.size() / BATCH_LIMIT);
                    for (int i = 0; i < batchCount; i++) {
                        int fromIdx = i * BATCH_LIMIT;
                        int toIdx = Math.min(fromIdx + BATCH_LIMIT, plansOfAccount.size());
                        List<AdPlanCreative> batch = plansOfAccount.subList(fromIdx, toIdx);

                        try {
                            int updated = syncBatch(tencentAds, accountId, batch);
                            totalUpdated += updated;
                        } catch (Exception e) {
                            log.error("[定时任务] 同步 accountId={} 的广告状态失败，batch index={}", accountId, i, e);
                        }
                    }
                }

                if (pageNum >= page.getPages()) {
                    break;
                }
                pageNum++;
            }

        } catch (Exception e) {
            log.error("[定时任务] 同步广告创意 system_status 发生异常", e);
        }

        log.info("[定时任务] 同步广告创意 system_status 完成，共更新 {} 条", totalUpdated);
        // 统计素材情况

        adPlanCreativeMapper.md5ApprovalCount();
    }

    @Async
    @Override
    public void syncAdPlanCreativeStatus(Long confId) {
        adPlanCreativeStatus(confId);
    }

    private int syncBatch(TencentAds tencentAds, Long accountId, List<AdPlanCreative> batch) throws Exception {
        final int BATCH_LIMIT = 100; // 腾讯广告 adgroup_id IN 最大 100
        final List<String> FIELDS = List.of("adgroup_id", "dynamic_creative_id", "configured_status", "creative_set_approval_status", "is_deleted");

        // 构建 adgroup_id IN [...] 过滤条件
        List<String> creativeIdValues = batch.stream()
                .map(p -> String.valueOf(p.getCreativeId()))
                .collect(Collectors.toList());

        FilteringStruct filter = new FilteringStruct();
        filter.setField("dynamic_creative_id");
        filter.setOperator(FilterOperator.IN);
        filter.setValues(creativeIdValues);

        List<FilteringStruct> filtering = new ArrayList<>();
        filtering.add(filter);

        
        DynamicCreativesGetResponseData response = tencentAds.dynamicCreatives().dynamicCreativesGet(
                accountId,
                filtering,
                1L, 
                (long) BATCH_LIMIT,
                FIELDS,
                null,
                "PAGINATION_MODE_NORMAL",
                null ,
                null        
        );

        if (response == null || response.getList() == null || response.getList().isEmpty()) {
            log.warn("[定时任务] accountId={} 未返回广告状态数据", accountId);
            return 0;
        }

        // 构建待更新列表
        List<AdPlanCreative> toUpdate = new ArrayList<>();
        response.getList().stream().forEach(item -> {
            AdPlanCreative update = new AdPlanCreative();
            update.setCreativeId(item.getDynamicCreativeId());
            update.setConfiguredStatus(item.getConfiguredStatus().getValue());
            update.setApprovalStatus(item.getCreativeSetApprovalStatus().getValue());
            update.setSystemDelete(item.isIsDeleted() != null ? String.valueOf(item.isIsDeleted()) : null);
            toUpdate.add(update);
        });

        if (toUpdate.isEmpty()) {
            return 0;
        }

        adPlanCreativeMapper.batchUpdateApprovalStatus(toUpdate);
        log.info("[定时任务] accountId={} 批量更新 {} 条 approval_status", accountId, toUpdate.size());
        return toUpdate.size();
    }


}
