package com.moka.gdtauto.service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.moka.gdtauto.client.TencentAdsApiClientFactory;
import com.moka.gdtauto.entity.TencentAdsAdgroup;
import com.moka.gdtauto.mapper.TencentAdsAdgroupMapper;
import com.tencent.ads.exception.TencentAdsResponseException;
import com.tencent.ads.exception.TencentAdsSDKException;
import com.tencent.ads.model.v3.*;
import com.tencent.ads.v3.TencentAds;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * 腾讯广告组服务
 * 
 * @author moka
 * @since 2026-02-04
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class TencentAdsAdgroupService extends ServiceImpl<TencentAdsAdgroupMapper, TencentAdsAdgroup> {

    private final TencentAdsAccountService accountService;
    private final TencentAdsAdgroupMapper adgroupMapper;
    private final TencentAdsApiClientFactory clientFactory;

    /**
     * 同步指定账户的广告组数据
     * 
     * @param accountId 账户ID
     * @param startTime 开始时间戳（可选）
     * @param endTime 结束时间戳（可选）
     * @return 同步的广告组数量
     */
    @Transactional(rollbackFor = Exception.class)
    public int syncAdgroups(String jobNumber, Long orgAccountId, Long accountId, Long startTime, Long endTime) throws Exception {
        log.info("开始同步广告组数据，jobNumber={}, orgAccountId={}, accountId={}, startTime={}, endTime={}", jobNumber, orgAccountId, accountId, startTime, endTime);
        
        int totalSynced = 0;
        Long page = 1L;
        Long pageSize = 100L; // 每页100条
        boolean hasMore = true;

        while (hasMore) {
            // 构建过滤条件
            List<FilteringStruct> filtering = buildFiltering(startTime, endTime);
            
            // 构建返回字段
            List<String> fields = buildFields();

            // 调用API获取数据
            AdgroupsGetResponseData response = accountService.getAdgroupsWithFiltering(
                jobNumber, orgAccountId, accountId, page, pageSize, filtering, fields);
            
            if (response == null || response.getList() == null || response.getList().isEmpty()) {
                hasMore = false;
                break;
            }
            
            // 批量保存数据
            List<TencentAdsAdgroup> adgroups = convertToEntity(response.getList(), accountId);
            batchSaveOrUpdate(adgroups);
            
            totalSynced += adgroups.size();
            log.info("已同步第{}页，本页{}条数据", page, adgroups.size());
            
            // 判断是否还有下一页
            if (response.getPageInfo() != null && 
                page >= response.getPageInfo().getTotalPage()) {
                hasMore = false;
            }
            
            page++;
        }
        
        log.info("同步完成，共同步{}条广告组数据", totalSynced);
        return totalSynced;
    }

    /**
     * 构建过滤条件
     */
    private List<FilteringStruct> buildFiltering(Long startTime, Long endTime) {
        if (startTime == null && endTime == null) {
            return null;
        }
        
        List<FilteringStruct> filtering = new ArrayList<>();
        
        if (startTime != null) {
            FilteringStruct filter = new FilteringStruct();
            filter.setField("last_modified_time");
            filter.setOperator(FilterOperator.GREATER_EQUALS);
            filter.setValues(List.of(String.valueOf(startTime)));
            filtering.add(filter);
        }
        
        if (endTime != null) {
            FilteringStruct filter = new FilteringStruct();
            filter.setField("last_modified_time");
            filter.setOperator(FilterOperator.LESS_EQUALS);
            filter.setValues(List.of(String.valueOf(endTime)));
            filtering.add(filter);
        }
        
        return filtering;
    }

    /**
     * 构建返回字段
     */
    private List<String> buildFields() {
        return List.of(
            // 保留的旧字段
            "adgroup_id",
            "adgroup_name",
            "configured_status",
            "daily_budget",
            "created_time",
            "marketing_scene",
            "last_modified_time",
            "is_deleted",
            // 新增字段
            "marketing_goal",
            "marketing_asset_outer_spec",
            "marketing_target_type",
            "marketing_asset_outer_id",
            "marketing_asset_outer_name",
            "marketing_carrier_type",
            "optimization_goal",
            "conversion_id",
            "site_set",
            "targeting",
            "bid_mode",
            "bid_scene",
            "begin_date",
            "end_date",
            "time_series",
            "auto_derived_creative_enabled",
            "creative_components"
        );
    }

    /**
     * 转换为实体对象
     */
    private List<TencentAdsAdgroup> convertToEntity(List<AdgroupsGetListStruct> apiList, Long accountId) {
        List<TencentAdsAdgroup> result = new ArrayList<>();
        
        for (AdgroupsGetListStruct api : apiList) {
            TencentAdsAdgroup entity = new TencentAdsAdgroup();
            entity.setAccountId(accountId);
            entity.setAdgroupId(api.getAdgroupId());
            entity.setAdgroupName(api.getAdgroupName());
            entity.setConfiguredStatus(api.getConfiguredStatus() != null ? 
                api.getConfiguredStatus().toString() : null);
            entity.setDailyBudget(api.getDailyBudget());
            entity.setCreatedTime(api.getCreatedTime());
            entity.setMarketingScene(api.getMarketingScene() != null ? 
                api.getMarketingScene().toString() : null);
            entity.setLastModifiedTime(api.getLastModifiedTime());
            
            // isDeleted字段处理（SDK中Boolean类型getter可能是isDeleted()）
            try {
                Boolean isDeleted = (Boolean) api.getClass().getMethod("isDeleted").invoke(api);
                entity.setIsDeleted(isDeleted != null && isDeleted ? 1 : 0);
            } catch (Exception e) {
                entity.setIsDeleted(0);
            }
            
            // 新增字段转换（根据SDK实际字段类型）
            // 枚举类型转String
            entity.setMarketingGoal(api.getMarketingGoal() != null ? api.getMarketingGoal().toString() : null);
            entity.setMarketingAssetOuterSpec(api.getMarketingAssetOuterSpec() != null ? api.getMarketingAssetOuterSpec().toString() : null);
            entity.setMarketingTargetType(api.getMarketingTargetType() != null ? api.getMarketingTargetType().toString() : null);
            entity.setMarketingCarrierType(api.getMarketingCarrierType() != null ? api.getMarketingCarrierType().toString() : null);
            entity.setOptimizationGoal(api.getOptimizationGoal() != null ? api.getOptimizationGoal().toString() : null);
            entity.setBidMode(api.getBidMode() != null ? api.getBidMode().toString() : null);
            entity.setBidScene(api.getBidScene() != null ? api.getBidScene().toString() : null);
            
            // Long类型转String
            entity.setConversionId(api.getConversionId() != null ? api.getConversionId().toString() : null);
            
            // List<String>转逗号分隔字符串
            if (api.getSiteSet() != null && !api.getSiteSet().isEmpty()) {
                entity.setSiteSet(String.join(",", api.getSiteSet()));
            }
            
            // 复杂对象转JSON字符串（ReadTargetingSetting）
            if (api.getTargeting() != null) {
                try {
                    entity.setTargeting(api.getTargeting().toString());
                } catch (Exception e) {
                    log.warn("转换targeting失败: {}", e.getMessage());
                }
            }
            
            // String类型直接赋值
            entity.setBeginDate(api.getBeginDate());
            entity.setEndDate(api.getEndDate());
            entity.setTimeSeries(api.getTimeSeries());
            
            // Boolean类型转String（使用反射处理）
            try {
                Boolean autoDerived = (Boolean) api.getClass().getMethod("getAutoDerivedCreativeEnabled").invoke(api);
                entity.setAutoDerivedCreativeEnabled(autoDerived != null ? autoDerived.toString() : null);
            } catch (Exception e) {
                // SDK不支持该字段
            }
            
            // creative_components - SDK中未找到此字段，保留为null
            // marketing_asset_outer_id - SDK中字段为marketingAssetId (Long)
            entity.setMarketingAssetOuterId(api.getMarketingAssetId() != null ? 
                api.getMarketingAssetId().toString() : null);
            
            // marketing_asset_outer_name - SDK中未找到，使用conversionName代替
            entity.setMarketingAssetOuterName(api.getConversionName());
            
            result.add(entity);
        }
        
        return result;
    }

    /**
     * 批量保存或更新
     * 使用 INSERT INTO ... ON DUPLICATE KEY UPDATE
     */
    private void batchSaveOrUpdate(List<TencentAdsAdgroup> adgroups) {
        if (adgroups == null || adgroups.isEmpty()) {
            return;
        }
        
        // 使用MyBatis XML的批量插入方法
        adgroupMapper.batchInsertOrUpdate(adgroups);
        log.info("批量保存/更新{}条数据", adgroups.size());
    }

    /**
     * 创建广告
     * 
     * @param accountId 广告主账户ID
     * @param jobNumber 工号
     * @param request 创建广告请求参数
     * @return 创建成功的广告信息
     * @throws TencentAdsResponseException API响应异常
     * @throws TencentAdsSDKException SDK异常
     * @throws Exception 其他异常
     */
    public AdgroupsAddResponseData createAdgroup(String jobNumber, Long orgAccountId,  AdgroupsAddRequest request) 
            throws TencentAdsResponseException, TencentAdsSDKException, Exception {
        log.info("开始创建广告，orgAccountId={}, adgroupName={}", orgAccountId, request.getAdgroupName());
        
        // 获取TencentAds实例
        TencentAds tencentAds = clientFactory.getTencentAds(jobNumber, orgAccountId);
        return createAdgroup(tencentAds, request);
    }

    /**
     * 创建广告（复用TencentAds实例）
     * 
     * @param tencentAds TencentAds实例
     * @param request 创建广告请求参数
     * @return 创建成功的广告信息
     * @throws TencentAdsResponseException API响应异常
     * @throws TencentAdsSDKException SDK异常
     * @throws Exception 其他异常
     */
    public AdgroupsAddResponseData createAdgroup(TencentAds tencentAds, AdgroupsAddRequest request) 
            throws TencentAdsResponseException, TencentAdsSDKException, Exception {
        log.info("开始创建广告，adgroupName={}", request.getAdgroupName());
        
        tencentAds.setDebug(true);
        // 调用SDK创建广告
        AdgroupsAddResponseData response = tencentAds.adgroups()
            .adgroupsAdd(request);
        log.info("创建广告成功，adgroupId={}", 
            response.getAdgroupId());
        
        return response;
    }

}
