package com.moka.gdtauto.controller;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.moka.gdtauto.annotation.AuthUser;
import com.moka.gdtauto.common.Result;
import com.moka.gdtauto.controller.vo.CreateAdPlanConfRequest;
import com.moka.gdtauto.controller.vo.UpdateAdPlanConfRequest;
import com.moka.gdtauto.entity.AccountGroup;
import com.moka.gdtauto.entity.AccountGroupAccountRelationship;
import com.moka.gdtauto.entity.AdPlan;
import com.moka.gdtauto.entity.AdPlanConf;
import com.moka.gdtauto.entity.AdPlanCreative;
import com.moka.gdtauto.entity.OssFile;
import com.moka.gdtauto.entity.SysUser;
import com.moka.gdtauto.entity.TencentAssetDrama;
import com.moka.gdtauto.entity.TencentAssetFiction;
import com.moka.gdtauto.mapper.AccountGroupAccountRelationshipMapper;
import com.moka.gdtauto.mapper.OssFileMapper;
import com.moka.gdtauto.mapper.TencentAssetDramaMapper;
import com.moka.gdtauto.mapper.TencentAssetFictionMapper;
import com.moka.gdtauto.service.AccountGroupService;
import com.moka.gdtauto.service.AdPlanConfService;
import com.moka.gdtauto.service.AdPlanCreativeDailyReportService;
import com.moka.gdtauto.service.AdPlanCreativeService;
import com.moka.gdtauto.service.AdPlanDailyReportService;
import com.moka.gdtauto.service.AdPlanService;
import com.moka.gdtauto.service.OssFileService;
import com.moka.gdtauto.service.SysUserService;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 广告计划配置管理控制器
 *
 * @author moka
 * @since 2026-02-24
 */
@Tag(name = "广告计划配置管理", description = "广告计划配置的创建、更新、删除及查询")
@Slf4j
@RestController
@RequestMapping("/api/ad-plan-conf")
@RequiredArgsConstructor
public class AdPlanConfController {

    private final RedisTemplate<String, String> redisTemplate;
    private final AdPlanConfService adPlanConfService;
    private final AdPlanService adPlanService;
    private final AdPlanDailyReportService adPlanDailyReportService;
    private final AdPlanCreativeDailyReportService adPlanCreativeDailyReportService;
    private final AdPlanCreativeService adPlanCreativeService;
    private final AccountGroupAccountRelationshipMapper relationshipMapper;
    private final SysUserService sysUserService;
    private final AccountGroupService accountGroupService;
    private final TencentAssetDramaMapper tencentAssetDramaMapper;
    private final TencentAssetFictionMapper tencentAssetFictionMapper;
    private final OssFileService ossFileService;
    private final OssFileMapper ossFileMapper;

    @GetMapping("/gdtSuspendByConfId")
    public Result<Void> gdtSuspendByConfId(@NotNull Long confId) {
        AdPlanConf adPlanConf = adPlanConfService.getById(confId);
        if (adPlanConf == null) {
            return Result.fail("广告计划配置不存在");
        }
        String lockKey = "ad_plan_conf_suspend_all_lock_" + confId;
        Boolean isLocked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 1, TimeUnit.MINUTES);
        if (!isLocked) {
            return Result.fail("请勿重复操作");
        }
        adPlanConfService.gdtSuspendByConf(adPlanConf);
        adPlanConfService.lambdaUpdate()
                .eq(AdPlanConf::getId, confId)
                .set(AdPlanConf::getSystemSuspendProcessStatus, 1)
                .update();
        return Result.success("暂停执行中");
    }

    @PostMapping("/gdtSuspendByPlanIds/{confId}")
    public Result<Void> gdtSuspendByPlanIds(@PathVariable Long confId, @RequestBody List<Long> planIds) {
        if (planIds == null) {
            return Result.success("请选择要暂停广告");
        }
        AdPlanConf adPlanConf = adPlanConfService.getById(confId);
        if (adPlanConf == null) {
            return Result.fail("广告计划配置不存在");
        }
        String lockKey = "ad_plan_conf_suspend_selected_lock_" + confId;
        Boolean isLocked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 1, TimeUnit.MINUTES);
        if (!isLocked) {
            return Result.fail("请勿重复操作");
        }
        adPlanConfService.gdtSuspendByPlanIds(adPlanConf, planIds);
        adPlanConfService.lambdaUpdate()
                .eq(AdPlanConf::getId, confId)
                .set(AdPlanConf::getSystemSuspendProcessStatus, 1)
                .update();
        return Result.success();
    }

    @GetMapping("/gdtDeleteByConfId")
    public Result<Void> gdtDeleteByConfId(@NotNull Long confId) {
        AdPlanConf adPlanConf = adPlanConfService.getById(confId);
        if (adPlanConf == null) {
            return Result.fail("广告计划配置不存在");
        }
        String lockKey = "ad_plan_conf_delete_all_lock_" + confId;
        Boolean isLocked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 1, TimeUnit.MINUTES);
        if (!isLocked) {
            return Result.fail("请勿重复操作");
        }
        adPlanConfService.gdtDeleteByConf(adPlanConf);
        adPlanConfService.lambdaUpdate()
                .eq(AdPlanConf::getId, confId)
                .set(AdPlanConf::getSystemSuspendProcessStatus, 1)
                .update();
        return Result.success("暂停执行中");
    }

    @PostMapping("/gdtDeleteByPlanIds/{confId}")
    public Result<Void> gdtDeleteByPlanIds(@PathVariable Long confId, @RequestBody  List<Long> planIds) {
        if (planIds == null) {
            return Result.success("请选择要暂停广告");
        }
        AdPlanConf adPlanConf = adPlanConfService.getById(confId);
        if (adPlanConf == null) {
            return Result.fail("广告计划配置不存在");
        }
        String lockKey = "ad_plan_conf_delete_selected_lock_" + confId;
        Boolean isLocked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 1, TimeUnit.MINUTES);
        if (!isLocked) {
            return Result.fail("请勿重复操作");
        }
        adPlanConfService.gdtDeleteByPlanIds(adPlanConf, planIds);
        adPlanConfService.lambdaUpdate()
                .eq(AdPlanConf::getId, confId)
                .set(AdPlanConf::getSystemSuspendProcessStatus, 1)
                .update();
        return Result.success();
    }

    @Operation(summary = "预创建广告计划配置", description = "根据账户分组ID和配置ID，重新创建广告计划配置")
    @PostMapping("/reCreate")
    public Result<List<AdPlan>> reCreateAdPlanConf(
            @RequestBody UpdateAdPlanConfRequest request,
            @AuthUser SysUser sysUser) {
        try {
            AccountGroup accountGroup = accountGroupService.getById(request.getAccountGroupId());
            List<AccountGroupAccountRelationship> relationships = relationshipMapper.selectList(
                    new LambdaQueryWrapper<AccountGroupAccountRelationship>()
                            .eq(AccountGroupAccountRelationship::getGroupId, request.getAccountGroupId()));

            List<AdPlan> plans = buildPlans(sysUser.getJobNumber(), request, accountGroup, relationships);

            return Result.success(plans, "重新创建广告计划配置成功");
        } catch (Exception e) {
            log.error("重新创建广告计划配置失败", e);
            return Result.fail("重新创建广告计划配置失败: " + e.getMessage());
        }
    }

    public record TencentAsset(Integer assetType, Long assetId, String assetName) {
    }

    private List<AdPlan> buildPlans(String jobNumber, UpdateAdPlanConfRequest request, AccountGroup accountGroup,
            List<AccountGroupAccountRelationship> relationships) {
        String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String accountGroupName = accountGroup.getGroupName();
        List<OssFile> creativeFileArr = request.getCreativeFileArr();
        List<AdPlan> plans = new ArrayList<>();
        Integer dramaAmount = request.getDramaAmount();
        Integer fictionAmount = request.getFictionAmount();
        // 获取短剧 relationships.size * dramaAmount
        // 1短剧2小说3混合
        Integer assetType = request.getAssetType();
        // 1随机2最新
        Integer assetModel = request.getAssetModel();
        String targets = request.getTargets();
        String sites = request.getSites();
        String[] targetArray = targets.split(",");
        String[] siteArray = sites.split(",");
        List<TencentAsset> dramaAssets = new ArrayList<>();
        List<TencentAsset> fictionAssets = new ArrayList<>();
        if (assetType == 1 && dramaAmount > 0) {
            List<TencentAssetDrama> dramas = new ArrayList<>();
            if (assetModel == 1) {
                dramas = tencentAssetDramaMapper.selectList(
                        new LambdaQueryWrapper<TencentAssetDrama>().eq(TencentAssetDrama::getJobNumber, jobNumber)
                                .last("order by rand() limit " + dramaAmount * relationships.size()));
            } else {
                dramas = tencentAssetDramaMapper.randomNewAsset(jobNumber, dramaAmount * relationships.size() * 2,
                        dramaAmount * relationships.size());
            }

            if (dramas.size() < dramaAmount * relationships.size()) {
                throw new IllegalArgumentException("短剧数量不足，请在短剧资产管理同步");
            }
            dramaAssets = dramas.stream()
                    .map(drama -> new TencentAsset(1, drama.getMarketingAssetId(), drama.getMarketingAssetName()))
                    .toList();
        }
        if (assetType == 2 && fictionAmount > 0) {
            List<TencentAssetFiction> fictions = new ArrayList<>();
            if (assetModel == 1) {
                fictions = tencentAssetFictionMapper.selectList(
                        new LambdaQueryWrapper<TencentAssetFiction>().eq(TencentAssetFiction::getJobNumber, jobNumber)
                                .last("order by rand() limit " + fictionAmount * relationships.size()));
            } else {
                fictions = tencentAssetFictionMapper.randomNewAsset(jobNumber, fictionAmount * relationships.size() * 2,
                        fictionAmount * relationships.size());
            }
            if (fictions.size() < fictionAmount * relationships.size()) {
                throw new IllegalArgumentException("小说数量不足，请在小说资产管理同步");
            }
            fictionAssets = fictions.stream()
                    .map(fiction -> new TencentAsset(2, fiction.getMarketingAssetId(), fiction.getMarketingAssetName()))
                    .toList();
        }
        if (assetType == 3) {
            if (dramaAmount > 0) {
                List<TencentAssetDrama> dramas = new ArrayList<>();
                if (assetModel == 1) {
                    dramas = tencentAssetDramaMapper.selectList(
                            new LambdaQueryWrapper<TencentAssetDrama>().eq(TencentAssetDrama::getJobNumber, jobNumber)
                                    .last("order by rand() limit " + dramaAmount * relationships.size()));
                } else {
                    dramas = tencentAssetDramaMapper.randomNewAsset(jobNumber, dramaAmount * relationships.size() * 2,
                            dramaAmount * relationships.size());
                }
                if (dramas.size() < dramaAmount * relationships.size()) {
                    throw new IllegalArgumentException("短剧数量不足，请在短剧资产管理同步");
                }
                dramaAssets.addAll(dramas.stream()
                        .map(drama -> new TencentAsset(1, drama.getMarketingAssetId(), drama.getMarketingAssetName()))
                        .toList());
            }
            if (fictionAmount > 0) {
                List<TencentAssetFiction> fictions = new ArrayList<>();
                if (assetModel == 1) {
                    fictions = tencentAssetFictionMapper.selectList(new LambdaQueryWrapper<TencentAssetFiction>()
                            .eq(TencentAssetFiction::getJobNumber, jobNumber)
                            .last("order by rand() limit " + fictionAmount * relationships.size()));
                } else {
                    fictions = tencentAssetFictionMapper.randomNewAsset(jobNumber,
                            fictionAmount * relationships.size() * 2, fictionAmount * relationships.size());
                }
                if (fictions.size() < fictionAmount * relationships.size()) {
                    throw new IllegalArgumentException("小说数量不足，请在小说资产管理同步");
                }
                fictionAssets.addAll(fictions.stream().map(
                        fiction -> new TencentAsset(2, fiction.getMarketingAssetId(), fiction.getMarketingAssetName()))
                        .toList());
            }
        }

        
        int dramaIndex = 0;
        int fictionIndex = 0;
        int planIndex = 0;
        System.out.println("dramaSize: " + dramaAssets.size() + " fictionSize: " + fictionAssets.size());
        for (AccountGroupAccountRelationship relationship : relationships) {
            if ((assetType == 1 || assetType == 3) && dramaAmount > 0) {
                for (int i = 0; i < dramaAmount; i++) {
                    System.out.println("dramaIndex: " + dramaIndex);
                    Long assetId = dramaAssets.get(dramaIndex).assetId();
                    String assetName = dramaAssets.get(dramaIndex).assetName();
                    Integer asset_type = dramaAssets.get(dramaIndex).assetType();
                    for (String target : targetArray) {
                        for (String site : siteArray) {
                            dramaIndex++;
                            planIndex++;
                            // 创建广告计划配置
                            // 广告名称：一般是“账户分组名”+“日期时间”+"自增编号"
                            String planName = accountGroupName.trim() + "-" + dateTime + "-" + planIndex;
                            AdPlan adPlan = new AdPlan();
                            adPlan.setAdPlanConfId(request.getId());
                            adPlan.setAccountId(relationship.getAccountId());
                            adPlan.setAdgroupId(0L);
                            adPlan.setAdgroupName(planName);
                            adPlan.setAdType(request.getAdType());
                            adPlan.setTarget(target);
                            adPlan.setSite(site);
                            adPlan.setConversionId(request.getConversionId());
                            adPlan.setAssetType(asset_type);
                            if (asset_type == 1) {
                                adPlan.setDramaId(assetId);
                                adPlan.setDramaName(assetName);
                            } else if (asset_type == 2) {
                                adPlan.setFictionId(assetId);
                                adPlan.setFictionName(assetName);
                            }
                            adPlan.setBidAmount(request.getBidAmount());
                            // adType=2-ROI
                            if (request.getAdType().equals(2)) {
                                adPlan.setDeepConversionWorthRate(request.getDeepConversionWorthRate());
                            } else {
                                adPlan.setDeepConversionWorthRate(BigDecimal.ZERO);
                            }
                            adPlan.setWxCorpid(request.getWxCorpid());
                            adPlan.setStatus(1);
                            plans.add(adPlan);
                            List<AdPlanCreative> adPlanCreatives = new ArrayList<>();
                            adPlan.setAdCreatives(adPlanCreatives);
                            int j = 0;
                            for (OssFile creativeFile : creativeFileArr) {
                                j++;
                                String creativeUrl = creativeFile.getFileUrl();
                                String originalFileName = creativeFile.getOriginalFileName();
                                // 去除文件后缀
                                String fileName = originalFileName != null
                                        ? originalFileName.replaceAll("\\.[^.]+$", "")
                                        : creativeUrl.substring(creativeUrl.lastIndexOf("/") + 1);
                                String creativeName = accountGroupName.trim() + "-" + dateTime + "-" + j + "-"
                                        + fileName;
                                AdPlanCreative adPlanCreative = new AdPlanCreative();
                                
                                adPlanCreative.setCreativeFileUrl(creativeUrl);
                                adPlanCreative.setCreativeFileMd5(creativeFile.getFileMd5());
                                adPlanCreative.setCreativeFileType(creativeFile.getFileType());
                                adPlanCreative.setCreativeId(0L);
                                adPlanCreative.setCreativeName(creativeName);
                                adPlanCreative.setCreativeText(request.getCreativeText());
                                adPlanCreative.setImageId(0L);
                                adPlanCreative.setVideoId(0L);
                                if (creativeFile.getFileType().equals("image")) {
                                    adPlanCreative.setImageId(Long.valueOf(creativeFile.getAssetId()));
                                } else if (creativeFile.getFileType().equals("video")) {
                                    adPlanCreative.setVideoId(Long.valueOf(creativeFile.getAssetId()));
                                }
                                adPlanCreative.setBrandImageId(0L);
                                adPlanCreative.setBrandName(request.getBrandName());
                                adPlanCreative.setBrandImageUrl(request.getBrandImageFile().getFileUrl());
                                adPlanCreative.setBrandImageFileMd5(request.getBrandImageFile().getFileMd5());
                                adPlanCreative.setButtonText(request.getButtonText());
                                adPlanCreative.setPageIds(request.getPageIds());
                                adPlanCreative.setStatus(1);
                                adPlanCreatives.add(adPlanCreative);
                            }
                        }
                    }
                }

            }
            if ((assetType == 2 || assetType == 3) && fictionAmount > 0) {
                for (int j = 0; j < fictionAmount; j++) {
                    Long assetId = fictionAssets.get(fictionIndex).assetId();
                    String assetName = fictionAssets.get(fictionIndex).assetName();
                    Integer asset_type = fictionAssets.get(fictionIndex).assetType();
                    System.out.println("fictionIndex: " + fictionIndex);
                    for (String target : targetArray) {
                        for (String site : siteArray) {
                            fictionIndex++;
                            planIndex++;
                            // 创建广告计划配置
                            // 广告名称：一般是“账户分组名”+“日期时间”+"自增编号"
                            String planName = accountGroupName.trim() + "-" + dateTime + "-" + planIndex;
                            AdPlan adPlan = new AdPlan();
                            adPlan.setAdPlanConfId(request.getId());
                            adPlan.setAccountId(relationship.getAccountId());
                            adPlan.setAdgroupId(0L);
                            adPlan.setAdgroupName(planName);
                            adPlan.setAdType(request.getAdType());
                            adPlan.setTarget(target);
                            adPlan.setSite(site);
                            adPlan.setConversionId(request.getConversionId());
                            adPlan.setAssetType(asset_type);
                            if (asset_type == 1) {
                                adPlan.setDramaId(assetId);
                                adPlan.setDramaName(assetName);
                            } else if (asset_type == 2) {
                                adPlan.setFictionId(assetId);
                                adPlan.setFictionName(assetName);
                            }
                            adPlan.setBidAmount(request.getBidAmount());
                            // adType=2-ROI
                            if (request.getAdType().equals(2)) {
                                adPlan.setDeepConversionWorthRate(request.getDeepConversionWorthRate());
                            } else {
                                adPlan.setDeepConversionWorthRate(BigDecimal.ZERO);
                            }
                            adPlan.setWxCorpid(request.getWxCorpid());
                            adPlan.setStatus(1);
                            plans.add(adPlan);
                            List<AdPlanCreative> adPlanCreatives = new ArrayList<>();
                            adPlan.setAdCreatives(adPlanCreatives);
                            int ci = 0;
                            for (OssFile creativeFile : creativeFileArr) {
                                ci++;
                                String creativeUrl = creativeFile.getFileUrl();
                                String originalFileName = creativeFile.getOriginalFileName();
                                // 去除文件后缀
                                String fileName = originalFileName != null
                                        ? originalFileName.replaceAll("\\.[^.]+$", "")
                                        : creativeUrl.substring(creativeUrl.lastIndexOf("/") + 1);
                                String creativeName = accountGroupName.trim() + "-" + dateTime + "-" + ci + "-"
                                        + fileName;
                                AdPlanCreative adPlanCreative = new AdPlanCreative();
                                adPlanCreative.setCreativeFileUrl(creativeUrl);
                                adPlanCreative.setCreativeFileMd5(creativeFile.getFileMd5());
                                adPlanCreative.setCreativeFileType(creativeFile.getFileType());
                                adPlanCreative.setCreativeId(0L);
                                adPlanCreative.setCreativeName(creativeName);
                                adPlanCreative.setCreativeText(request.getCreativeText());
                                adPlanCreative.setImageId(0L);
                                adPlanCreative.setVideoId(0L);
                                if (creativeFile.getFileType().equals("image")) {
                                    adPlanCreative.setImageId(Long.valueOf(creativeFile.getAssetId()));
                                } else if (creativeFile.getFileType().equals("video")) {
                                    adPlanCreative.setVideoId(Long.valueOf(creativeFile.getAssetId()));
                                }
                                adPlanCreative.setBrandImageId(0L);
                                adPlanCreative.setBrandName(request.getBrandName());
                                adPlanCreative.setBrandImageUrl(request.getBrandImageFile().getFileUrl());
                                adPlanCreative.setBrandImageFileMd5(request.getBrandImageFile().getFileMd5());
                                adPlanCreative.setButtonText(request.getButtonText());
                                adPlanCreative.setPageIds(request.getPageIds());
                                adPlanCreative.setStatus(1);
                                adPlanCreatives.add(adPlanCreative);
                            }
                        }
                    }
                }

            }
        }
        return plans;
    }

    @PostMapping("/generate-plan")
    public Result<AdPlanConf> generatePlan(
            @RequestBody UpdateAdPlanConfRequest request,
            @AuthUser SysUser sysUser) {

        SysUser user = sysUserService.getById(sysUser.getId());
        LocalDateTime userTokenExpiresAt = user.getUserTokenExpiresAt();
        if (userTokenExpiresAt == null || userTokenExpiresAt.isBefore(LocalDateTime.now())) {
            return Result.fail("实名认证已过期");
        }

        try {
            AccountGroup accountGroup = accountGroupService.getById(request.getAccountGroupId());
            List<AccountGroupAccountRelationship> relationships = relationshipMapper.selectList(
                    new LambdaQueryWrapper<AccountGroupAccountRelationship>()
                            .eq(AccountGroupAccountRelationship::getGroupId, request.getAccountGroupId()));
            Long confId = request.getId();
            AdPlanConf adPlanConf = new AdPlanConf();
            if (confId == null) {
                BeanUtils.copyProperties(request, adPlanConf);
                adPlanConf.setCreativeFiles(JSON.toJSONString(request.getCreativeFileArr()));
                adPlanConf.setBrandImageFile(JSON.toJSONString(request.getBrandImageFile()));
                adPlanConf.setUserId(sysUser.getId());
                adPlanConf.setJobNumber(sysUser.getJobNumber());
                adPlanConf.setCreator(sysUser.getName());
                confId = adPlanConfService.createAdPlanConf(adPlanConf);
                request.setId(confId);
            } else {
                BeanUtils.copyProperties(request, adPlanConf);
                adPlanConfService.updateAdPlanConf(adPlanConf);
            }
            List<AdPlan> plans = buildPlans(sysUser.getJobNumber(), request, accountGroup, relationships);
            for (AdPlan plan : plans) {
                plan.setAdPlanConfId(confId);
            }
            adPlanConfService.savePlanAndCreative(plans);
            // 异步对接腾讯接口
            AdPlanConf savedConf = adPlanConfService.getById(confId);
            adPlanConfService.asyncTencentInterface(savedConf, plans);

            return Result.success(adPlanConf, "创建广告计划成功;异步执行接口对接中");
        } catch (Exception e) {
            log.error("创建广告计划失败", e);
            return Result.fail("创建广告计划失败: " + e.getMessage());
        }
    }

    @GetMapping("/reGeneratePlan/{id}")
    public Result<Void> reGeneratePlan(@PathVariable Long id, @AuthUser SysUser sysUser) {
        SysUser user = sysUserService.getById(sysUser.getId());
        LocalDateTime userTokenExpiresAt = user.getUserTokenExpiresAt();
        if (userTokenExpiresAt == null || userTokenExpiresAt.isBefore(LocalDateTime.now())) {
            return Result.fail("实名认证已过期");
        }
        adPlanConfService.asyncReGeneratePlan(id);
        return Result.success("重新生成广告计划执行中");
    }

    @GetMapping("/syncSystemStatus/{id}")
    public Result<Void> syncSystemStatus(@PathVariable Long id, @AuthUser SysUser sysUser) {
        // redis锁 1分钟
        String lockKey = "ad_plan_conf_sync_system_status_lock_" + id;
        Boolean isLocked = redisTemplate.opsForValue().setIfAbsent(lockKey, "1", 1, TimeUnit.MINUTES);
        if (!isLocked) {
            return Result.fail("请勿重复操作");
        }
        adPlanService.syncAdPlanStatus(id);
        adPlanCreativeService.syncAdPlanCreativeStatus(id);
        adPlanDailyReportService.syncDailyReport(id);
        adPlanCreativeDailyReportService.syncDailyReport(id);
        try {
            TimeUnit.SECONDS.sleep(2L);
        } catch (InterruptedException e) {
        }
        return Result.success("同步系统状态执行中");
    }

    /**
     * 创建广告计划配置
     */
    @Operation(summary = "创建广告计划配置", description = "为当前用户创建新的广告计划配置")
    @PostMapping("/create")
    public Result<Long> createAdPlanConf(
            @RequestBody CreateAdPlanConfRequest request,
            @AuthUser SysUser sysUser) {
        try {
            AdPlanConf adPlanConf = new AdPlanConf();
            BeanUtils.copyProperties(request, adPlanConf);
            adPlanConf.setCreativeFiles(JSON.toJSONString(request.getCreativeFileArr()));
            adPlanConf.setBrandImageFile(JSON.toJSONString(request.getBrandImageFile()));
            adPlanConf.setUserId(sysUser.getId());
            adPlanConf.setJobNumber(sysUser.getJobNumber());
            adPlanConf.setCreator(sysUser.getName());

            Long confId = adPlanConfService.createAdPlanConf(adPlanConf);
            return Result.success(confId, "创建广告计划配置成功");
        } catch (Exception e) {
            log.error("创建广告计划配置失败", e);
            return Result.fail("创建广告计划配置失败: " + e.getMessage());
        }
    }

    /**
     * 更新广告计划配置
     */
    @Operation(summary = "更新广告计划配置", description = "更新指定的广告计划配置")
    @PostMapping("/update")
    public Result<Void> updateAdPlanConf(
            @RequestBody UpdateAdPlanConfRequest request,
            @AuthUser SysUser sysUser) {
        try {
            AdPlanConf adPlanConf = new AdPlanConf();
            BeanUtils.copyProperties(request, adPlanConf);
            adPlanConf.setCreativeFiles(JSON.toJSONString(request.getCreativeFileArr()));
            adPlanConf.setBrandImageFile(JSON.toJSONString(request.getBrandImageFile()));
            boolean success = adPlanConfService.updateAdPlanConf(adPlanConf);
            if (success) {
                return Result.success("更新广告计划配置成功");
            } else {
                return Result.fail("广告计划配置不存在或无权限");
            }
        } catch (Exception e) {
            log.error("更新广告计划配置失败", e);
            return Result.fail("更新广告计划配置失败: " + e.getMessage());
        }
    }

    /**
     * 删除广告计划配置
     */
    @Operation(summary = "删除广告计划配置", description = "删除指定的广告计划配置")
    @DeleteMapping("/{confId}")
    public Result<Void> deleteAdPlanConf(
            @Parameter(description = "配置ID", required = true) @PathVariable Long confId,
            @AuthUser SysUser sysUser) {
        try {
            boolean success = adPlanConfService.deleteAdPlanConf(confId, sysUser.getId());
            if (success) {
                return Result.success("删除广告计划配置成功");
            } else {
                return Result.fail("广告计划配置不存在或无权限");
            }
        } catch (Exception e) {
            log.error("删除广告计划配置失败", e);
            return Result.fail("删除广告计划配置失败: " + e.getMessage());
        }
    }

    /**
     * 获取用户的广告计划配置列表（分页）
     */
    @Operation(summary = "获取广告计划配置列表", description = "分页获取当前用户的所有广告计划配置")
    @GetMapping("/list")
    public Result<Page<AdPlanConf>> getAdPlanConfs(
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Integer pageSize,
            @Parameter(description = "查询范围：1-我的，2-全部") @RequestParam(defaultValue = "2") Integer queryScope,
            @Parameter(description = "计划名称") @RequestParam(required = false) String name,
            @Parameter(description = "状态") @RequestParam(required = false) Integer status,
            @Parameter(description = "创建开始时间") @RequestParam(required = false) String createTimeStart,
            @Parameter(description = "创建结束时间") @RequestParam(required = false) String createTimeEnd,
            @AuthUser SysUser sysUser) {
        try {
            LambdaQueryWrapper<AdPlanConf> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(AdPlanConf::getDeleted, 0);
            
            // 查询范围：1-我的，2-全部
            if (queryScope != null && queryScope == 1) {
                wrapper.eq(AdPlanConf::getUserId, sysUser.getId());
            }
            
            // 名称模糊查询
            if (name != null && !name.trim().isEmpty()) {
                wrapper.like(AdPlanConf::getName, name.trim());
            }
            
            // 状态查询
            if (status != null) {
                wrapper.eq(AdPlanConf::getStatus, status);
            }
            
            // 创建时间范围查询
            if (createTimeStart != null && !createTimeStart.isEmpty()) {
                wrapper.ge(AdPlanConf::getCreateTime, createTimeStart);
            }
            if (createTimeEnd != null && !createTimeEnd.isEmpty()) {
                wrapper.le(AdPlanConf::getCreateTime, createTimeEnd);
            }
            
            // 按ID降序排列
            wrapper.orderByDesc(AdPlanConf::getId);
            
            Page<AdPlanConf> page = new Page<>(pageNum, pageSize);
            page = adPlanConfService.page(page, wrapper);
            return Result.success(page, "查询成功");
        } catch (Exception e) {
            log.error("查询广告计划配置列表失败", e);
            return Result.fail("查询广告计划配置列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取用户的广告计划配置列表（分页）
     */
    @Operation(summary = "获取广告计划配置列表", description = "分页获取当前用户的所有广告计划配置")
    public Result<Page<AdPlanConf>> getMyAdPlanConfigList(
             @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer pageNum,
             @Parameter(description = "每页大小", example = "10") @RequestParam(defaultValue = "10") Integer pageSize,
            @AuthUser SysUser sysUser) {
        try {
            Page<AdPlanConf> page = adPlanConfService.getUserAdPlanConfs(
                    sysUser.getId(), pageNum, pageSize, true);
            return Result.success(page, "查询成功");
        } catch (Exception e) {
            log.error("查询广告计划配置列表失败", e);
            return Result.fail("查询广告计划配置列表失败: " + e.getMessage());
        }
    }

    /**
     * 获取广告计划配置详情
     */
    @Operation(summary = "获取广告计划配置详情", description = "根据ID获取广告计划配置详细信息")
    @GetMapping("/{confId}")
    public Result<AdPlanConf> getAdPlanConf(
            @Parameter(description = "配置ID", required = true) @PathVariable Long confId,
            @AuthUser SysUser sysUser) {
        try {
            AdPlanConf adPlanConf = adPlanConfService.getAdPlanConfById(confId, sysUser.getId());
            if (adPlanConf != null) {
                return Result.success(adPlanConf, "查询成功");
            } else {
                return Result.fail("广告计划配置不存在或无权限");
            }
        } catch (Exception e) {
            log.error("查询广告计划配置详情失败", e);
            return Result.fail("查询广告计划配置详情失败: " + e.getMessage());
        }
    }


    @PostMapping("/getOneCreativeImage")
    public Result<OssFile> getOneCreativeImage(@RequestBody List<Long> ids) {
        try {
            OssFile ossFile = ossFileMapper.selectOneCreativeImage(ids);
            return Result.success(ossFile, "查询成功");
        } catch (Exception e) {
            log.error("查询创意图片失败", e);
            return Result.fail("查询创意图片失败: " + e.getMessage());
        }
    }

    @PostMapping("/getOneCreativeVideo")
    public Result<OssFile> getOneCreativeVideo(@RequestBody List<Long> ids) {
        try {
            OssFile ossFile = ossFileMapper.selectOneCreativeVideo(ids);
            return Result.success(ossFile, "查询成功");
        } catch (Exception e) {
            log.error("查询创意视频失败", e);
            return Result.fail("查询创意视频失败: " + e.getMessage());
        }
    }

    @GetMapping("/getOneBrandImage")
    public Result<OssFile> getOneBrandImage() {
        try {
            OssFile ossFile = ossFileService.lambdaQuery()
                    .eq(OssFile::getBusinessType, 2)
                    .eq(OssFile::getFileType, "image")
                    .last("order by rand() limit 1").one();
            return Result.success(ossFile, "查询成功");
        } catch (Exception e) {
            log.error("查询品牌图片失败", e);
            return Result.fail("查询品牌图片失败: " + e.getMessage());
        }
    }
}
