package ctop.bytedance.ad.advertise.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import ctop.bytedance.ad.advertise.dockapi.MarketingService;
import ctop.bytedance.ad.advertise.entity.AiBytedanceAdvertiserStrategy;
import ctop.bytedance.ad.advertise.entity.RuleDataAccount;
import ctop.bytedance.ad.advertise.entity.UpdAdStaOrCpaOrBudget;
import ctop.bytedance.ad.advertise.service.IAiBytedanceAdvertiserStrategyService;
import ctop.bytedance.ad.advertise.service.IRuleDataAccountService;
import ctop.bytedance.ad.advertise.vo.AdConvertQueryVo;
import ctop.bytedance.ad.advertise.vo.AdGroupSearchVo;
import ctop.bytedance.ad.advertise.vo.PlanSearchVo;
import ctop.bytedance.ad.common.constant.BytedanceConstant;
import ctop.bytedance.ad.common.entity.CtopOauthToken;
import ctop.bytedance.ad.common.entity.MaterialImageInfo;
import ctop.bytedance.ad.common.entity.UserAllocation;
import ctop.bytedance.ad.common.service.ICtopOauthTokenService;
import ctop.bytedance.ad.common.service.IMaterialImageInfoService;
import ctop.bytedance.ad.common.service.IUserAllocationService;
import ctop.bytedance.ad.common.utils.*;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.api.ICommonService;
import org.jeecg.common.system.query.QueryGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 头条智能投放账户配置信息表
 * @author jeecg-boot
 * @date   2021-04-20
 * @version V1.0
 */
@RestController
@RequestMapping("/bytedance/ad/advertiser/aiBytedanceAdvertiserStrategy")
@Api(tags="头条智能投放账户配置信息表")
@Slf4j
public class AiBytedanceAdvertiserStrategyController {
	@Autowired
	private IAiBytedanceAdvertiserStrategyService aiBytedanceAdvertiserStrategyService;
	@Autowired
	private IRuleDataAccountService ruleDataAccountService;
	@Autowired
	private IMaterialImageInfoService materialImageInfoService;
	@Autowired
	private MarketingService marketingService;
	@Autowired
	private ICtopOauthTokenService tokenService;
	@Autowired
	private IUserAllocationService userAllocationService;
	@Reference
	private ICommonService commonService;

	/**
	  * 分页列表查询
	 * @param aiBytedanceAdvertiserStrategy
	 * @param pageNo
	 * @param pageSize
	 * @param req
	 * @return
	 */
	@ApiOperation(value="头条智能投放账户配置信息表-分页列表查询", notes="头条智能投放账户配置信息表-分页列表查询")
	@GetMapping(value = "/list")
	public Result<IPage<AiBytedanceAdvertiserStrategy>> queryPageList(AiBytedanceAdvertiserStrategy aiBytedanceAdvertiserStrategy,
																	  @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
																	  @RequestParam(name="pageSize", defaultValue="10") Integer pageSize,
																	  HttpServletRequest req) {
		Result<IPage<AiBytedanceAdvertiserStrategy>> result = new Result<>();
		QueryWrapper<AiBytedanceAdvertiserStrategy> queryWrapper = QueryGenerator.initQueryWrapper(aiBytedanceAdvertiserStrategy, req.getParameterMap());
		//获取用户角色code
		String roleCode = commonService.getRoleCodeByUserId(aiBytedanceAdvertiserStrategy.getLoginUserId());
		if(null != roleCode && !BytedanceConstant.COMMON_ROLE_CODE_ADMIN.equals(roleCode)){
			queryWrapper.eq("user_id", aiBytedanceAdvertiserStrategy.getLoginUserId());
		}
		queryWrapper.orderByDesc("create_time");
		Page<AiBytedanceAdvertiserStrategy> page = new Page<>(pageNo, pageSize);
		//查询
		IPage<AiBytedanceAdvertiserStrategy> pageList = aiBytedanceAdvertiserStrategyService.page(page, queryWrapper);
		pageList.getRecords().forEach(pojo ->{
			if (!Check.isNull(pojo.getAccountId())){
				UserAllocation allocation = userAllocationService.getByAccountId(pojo.getAccountId());
				if(null!=allocation){
					pojo.setAccountName(allocation.getAuthName());
				}
				QueryWrapper<RuleDataAccount> ruleDataAccountQueryWrapper = new QueryWrapper<>();
				ruleDataAccountQueryWrapper.eq("account_id",pojo.getAccountId());
				//获取消耗 余额
				RuleDataAccount ruleDataAccountVo =  ruleDataAccountService.getOne(ruleDataAccountQueryWrapper);
				if (!Check.isNull(ruleDataAccountVo)){
					//消耗
					pojo.setCost(ruleDataAccountVo.getCost());
					//余额
					pojo.setValidBalance(ruleDataAccountVo.getValidBalance());
				}else {
					pojo.setCost(new BigDecimal(0));
					pojo.setValidBalance(new BigDecimal(0));
				}
				//拼接 目标转化出价
				pojo.setAdCpaBidStr("FIX".equalsIgnoreCase(pojo.getAdBidCreateType()) ? pojo.getAdCpaBid().toString() : (pojo.getAdMinBid() + "~" + pojo.getAdMaxBid()));
			}
		});

		result.setSuccess(true);
		result.setResult(pageList);
		return result;
	}

	/**
	  *   添加配置信息
	 * @param aiBytedanceAdvertiserStrategy
	 * @return
	 */
	@ApiOperation(value="头条智能投放账户配置信息表-添加", notes="头条智能投放账户配置信息表-添加")
	@PostMapping(value = "/addBytedanceStrategy")
	public Result addBytedanceStrategy(@RequestBody AiBytedanceAdvertiserStrategy aiBytedanceAdvertiserStrategy) {
		try {
			//复制功能 防止前端传id到后台
			aiBytedanceAdvertiserStrategy.setId(null);
			return aiBytedanceAdvertiserStrategyService.addBytedanceStrategy(aiBytedanceAdvertiserStrategy);
		} catch (Exception e) {
			log.error(e.getMessage(),e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}

	/**
	  *  编辑
	 * @param aiBytedanceAdvertiserStrategy
	 * @return
	 */
	@ApiOperation(value="头条智能投放账户配置信息表-编辑", notes="头条智能投放账户配置信息表-编辑")
	@PutMapping(value = "/edit")
	public Result<AiBytedanceAdvertiserStrategy> edit(@RequestBody AiBytedanceAdvertiserStrategy aiBytedanceAdvertiserStrategy) {
		CtopOauthToken token = tokenService.getOauthTokenByAccountId(String.valueOf(aiBytedanceAdvertiserStrategy.getAccountId()));
		//修改后预算金额不能低于当前已消费金额的105%
		QueryWrapper<RuleDataAccount> ruleDataAccountQueryWrapper = new QueryWrapper<>();
		ruleDataAccountQueryWrapper.eq("account_id",aiBytedanceAdvertiserStrategy.getAccountId());
		//获取消耗 余额
		RuleDataAccount ruleDataAccountVo = ruleDataAccountService.getOne(ruleDataAccountQueryWrapper);
		// 值 为0 不限预算
		// ！0 指定预算
		if (!aiBytedanceAdvertiserStrategy.getAccountBudget().equals(new BigDecimal("0"))){
			//花费 0 不校验
			int zero= Check.isNull(ruleDataAccountVo) ? 0 : ruleDataAccountVo.getCost().compareTo(BigDecimal.ZERO);
			if (zero != 0){
				//  前者 < 后者
				int a = aiBytedanceAdvertiserStrategy.getAccountBudget().compareTo(ruleDataAccountVo.getCost().multiply(new BigDecimal(1.05)));
				if (a == -1){
					return Result.errorMsg("预算金额不能低于当前已消费金额的105%");
				}
			}
		}

		//不修改用户id
		aiBytedanceAdvertiserStrategy.setUserId(null);
		//商品卖点
		aiBytedanceAdvertiserStrategy.setCreativeProductSellingPoints(StringUtils.join(aiBytedanceAdvertiserStrategy.getProductSellingPoints(), ","));
		//广告位置
		aiBytedanceAdvertiserStrategy.setCreativeInventoryType(StringUtils.join(aiBytedanceAdvertiserStrategy.getCreativeInventoryTypes(), ","));
		//创意标签
		aiBytedanceAdvertiserStrategy.setCreativeAdKeywords(StringUtils.join(aiBytedanceAdvertiserStrategy.getAdKeywords(), ","));

		AiBytedanceAdvertiserStrategy aiBytedanceAdvertiserStrategyEntity = aiBytedanceAdvertiserStrategyService.getById(aiBytedanceAdvertiserStrategy.getId());
		if (aiBytedanceAdvertiserStrategyEntity == null) {
			return Result.errorMsg("未找到对应实体");
		} else {
			boolean ok = aiBytedanceAdvertiserStrategyService.updateById(aiBytedanceAdvertiserStrategy);
			if (!ok) {
				return Result.errorMsg("修改失败!");
			}
			//账户预算 同步 头条
			//BUDGET_MODE_DAY-日预算
			// BUDGET_MODE_INFINITE-不限
			String accountBudgetMode = "1".equals(aiBytedanceAdvertiserStrategy.getAccountBudgetMode()) ? "BUDGET_MODE_INFINITE" : "BUDGET_MODE_DAY";
			Result resultBudget = marketingService.updateBudget(token,accountBudgetMode,aiBytedanceAdvertiserStrategy.getAccountBudget());
		}
		return Result.successMsg("修改成功!", null);

	}

	/**
	  *   通过id删除
	 * @param id
	 * @return
	 */
	@ApiOperation(value="头条智能投放账户配置信息表-通过id删除", notes="头条智能投放账户配置信息表-通过id删除")
	@DeleteMapping(value = "/delete")
	public Result<?> delete(@RequestParam(name="id") String id) {
		try {
			aiBytedanceAdvertiserStrategyService.removeById(id);
		} catch (Exception e) {
			log.error("删除失败",e);
			return Result.error("删除失败!");
		}
		return Result.successMsg("删除成功!",null);
	}

	/**
	 *  批量删除
	 * @param ids
	 * @return
	 */
	@ApiOperation(value="头条智能投放账户配置信息表-批量删除", notes="头条智能投放账户配置信息表-批量删除")
	@DeleteMapping(value = "/deleteBatch")
	public Result<AiBytedanceAdvertiserStrategy> deleteBatch(@RequestParam(name="ids") String ids) {
		Result<AiBytedanceAdvertiserStrategy> result = new Result<>();
		if(ids==null || "".equals(ids.trim())) {
			result.error500("参数不识别！");
		}else {
			this.aiBytedanceAdvertiserStrategyService.removeByIds(Arrays.asList(ids.split(",")));
			result.success("删除成功!");
		}
		return result;
	}

	/**
	  * 通过id查询
	 * @param id
	 * @return
	 */
	@ApiOperation(value="头条智能投放账户配置信息表-通过id查询", notes="头条智能投放账户配置信息表-通过id查询")
	@GetMapping(value = "/queryById")
	public Result<AiBytedanceAdvertiserStrategy> queryById(@RequestParam(name="id",required=true) String id) {
		Result<AiBytedanceAdvertiserStrategy> result = new Result<>();
		AiBytedanceAdvertiserStrategy aiBytedanceAdvertiserStrategy = aiBytedanceAdvertiserStrategyService.getById(id);
		if(aiBytedanceAdvertiserStrategy==null) {
			result.error500("未找到对应实体");
		}else {
			//商品卖点
			if (!Check.isNull(aiBytedanceAdvertiserStrategy.getCreativeProductSellingPoints())){
				aiBytedanceAdvertiserStrategy.setProductSellingPoints(aiBytedanceAdvertiserStrategy.getCreativeProductSellingPoints().split(","));
			}
			//广告位置
			if (!Check.isNull(aiBytedanceAdvertiserStrategy.getCreativeInventoryType())){
				aiBytedanceAdvertiserStrategy.setCreativeInventoryTypes(aiBytedanceAdvertiserStrategy.getCreativeInventoryType().split(","));
			}
			//创意标签
			if (!Check.isNull(aiBytedanceAdvertiserStrategy.getCreativeAdKeywords())){
				aiBytedanceAdvertiserStrategy.setAdKeywords(aiBytedanceAdvertiserStrategy.getCreativeAdKeywords().split(","));
			}
			//素材图片url
			MaterialImageInfo materialImageInfo = materialImageInfoService.getByCode(aiBytedanceAdvertiserStrategy.getCreativeProductImageCode());
			if(null!=materialImageInfo){
				aiBytedanceAdvertiserStrategy.setImageUrl(materialImageInfo.getUrl());
			}
			result.setResult(aiBytedanceAdvertiserStrategy);
			result.setSuccess(true);
		}
		return result;
	}

	@ApiOperation(value="头条智能投放账户配置信息-修改状态(0开-1关)", notes="头条智能投放账户配置信息-修改状态(0开-1关)")
	@PutMapping(value = "/updStaById")
	public Result updStaById(@RequestParam("id")String id,
							 @ApiParam("状态(0开-1关)") @RequestParam("state") String state,
							 @ApiParam("账户id") @RequestParam("accountId") String accountId,
							 @ApiParam("素材类型") @RequestParam("creativeImageMode") String creativeImageMode) {
		try {
			return aiBytedanceAdvertiserStrategyService.updStaById(id,state,accountId,creativeImageMode);
		}catch (Exception e){
			log.error("修改状态(0开-1关)失败",e);
			return Result.error("请求失败，请联系开发人员!");
		}

	}

	@ApiOperation(value="头条智能投放账户配置信息-修改出价;预算", notes="头条智能投放账户配置信息-修改出价;预算")
	@PutMapping(value = "/updStaOrCpaOrBudgetById")
	public Result updStaOrCpaOrBudgetById(UpdAdStaOrCpaOrBudget updAdStaOrCpaOrBudget) {
		try {
			return aiBytedanceAdvertiserStrategyService.updStaOrCpaOrBudgetById(updAdStaOrCpaOrBudget);
		}catch (Exception e){
			log.error("修改出价-预算失败",e);
			return Result.error("请求失败，请联系开发人员!");
		}

	}

	@ApiOperation(value="头条智能投放账户配置-获取行业类别", notes="头条智能投放账户配置-获取行业类别")
	@GetMapping(value = "/getIndustryList")
	public Result getIndustryList(@RequestParam("accountId") String accountId, @RequestParam(value = "type",defaultValue = "ADVERTISER") String type) {
		try {
			return aiBytedanceAdvertiserStrategyService.getIndustryList(accountId,type);
		}catch (Exception e){
			log.error("创建失败",e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}

	@ApiOperation(value="头条智能投放账户配置-获取广告组", notes="头条智能投放账户配置-获取广告组")
	@PostMapping(value = "/getCampaignGroupList")
	public Result getCampaignGroup(List<AdGroupSearchVo> adGroupSearchVoList,
								   @RequestParam("accountId") String accountId,
								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
		try {
			return aiBytedanceAdvertiserStrategyService.getCampaignGroup(accountId,adGroupSearchVoList,pageNo,pageSize);
		}catch (Exception e){
			log.error("获取广告组异常。",e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}

	@ApiOperation(value="头条智能投放账户配置-获取广告计划", notes="头条智能投放账户配置-获取广告计划")
	@PostMapping(value = "/getCampaignPlanList")
	public Result getCampaignPlanList(PlanSearchVo planSearchVoList,
								   @RequestParam("accountId") String accountId,
								   @RequestParam(name="pageNo", defaultValue="1") Integer pageNo,
								   @RequestParam(name="pageSize", defaultValue="10") Integer pageSize) {
		try {
			return aiBytedanceAdvertiserStrategyService.getCampaignPlan(accountId,planSearchVoList,pageNo,pageSize);
		}catch (Exception e){
			log.error("获取广告计划异常。",e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}

	@ApiOperation(value="头条智能投放账户配置-获取创意详细信息", notes="头条智能投放账户配置-获取创意详细信息")
	@PostMapping(value = "/creativeReadInfo")
	public Result creativeReadInfo(@RequestParam("accountId") String accountId,@RequestParam("adId") String adId) {
		try {
			return aiBytedanceAdvertiserStrategyService.creativeReadInfo(accountId,adId);
		}catch (Exception e){
			log.error("获取广告组异常。",e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}

	@ApiOperation(value="查询广告计划可用转化目标", notes="查询广告计划可用转化目标")
	@PostMapping(value = "/getToolConvert")
	public Result getToolConvert(@RequestBody AdConvertQueryVo adConvertQueryVo) {
		try {
			return aiBytedanceAdvertiserStrategyService.getToolConvert(adConvertQueryVo);
		}catch (Exception e){
			log.error("查询广告计划可用转化目标异常",e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}

	@ApiOperation(value="智能投放测试创建计划", notes="智能投放测试创建计划")
	@GetMapping("testCreateCreativeLimit")
	public Map<String, Object> testCreateCreativeLimit(Long accountId, Integer hour) {
		Map<String, Object> result = new HashMap<>();
		List<AiBytedanceAdvertiserStrategy> strategys = aiBytedanceAdvertiserStrategyService.getByAccountId(accountId,0);
		strategys.forEach(strategy->{
			aiBytedanceAdvertiserStrategyService.customCreativeSupplement(strategy, hour,strategy.getAdOpenUrl());
		});
		ResultMapUtils.setResultMap(result, StatusCode.COMMON_SUCCESS);
		return result;
	}

	static ExecutorService executorService = Executors.newFixedThreadPool(5);

	@GetMapping("autoCreateCreative")
	public Map<String, Object> autoCreateCreative(Integer hour) {
		Map<String, Object> result = new HashMap<>();
		List<AiBytedanceAdvertiserStrategy> strategys = aiBytedanceAdvertiserStrategyService.getByAccountId(null,0);
		if (strategys == null||strategys.isEmpty()) {
			ResultMapUtils.setResultMap(result, StatusCode.COMMON_PARAM_ERROR);
			return result;
		}
		strategys.forEach(strategy -> executorService.submit(()->{
			aiBytedanceAdvertiserStrategyService.customCreativeSupplement(strategy, hour,strategy.getAdOpenUrl());
		}));
		ResultMapUtils.setResultMap(result, StatusCode.COMMON_SUCCESS);
		return result;
	}

	/**
	 *
	 * 根据下载链接获取应用包名
	 *
	 * @param urlPath 下载链接
	 * @return org.jeecg.common.api.vo.Result
	 * @author zianY
	 */
	@ApiOperation(value="根据下载链接获取应用包名", notes="根据下载链接获取应用包名")
	@GetMapping(value = "/getPackageNameByUrl")
	public Result getPackageNameByUrl(@RequestParam("urlPath") String urlPath) {
		try {
			Map<String,Object> map = new HashMap();
			//根据下载链接上传附件
			urlPath = LoadFileUtil.downLoadFromUrl(urlPath, "appFiles");
			// android 根据附件地址 读取 apk 信息
			map = ApkUtils.readAPK(urlPath);
			if (!"-1".equals(map.get("code").toString())){
				map.put("platform", "APP_ANDROID");
			}else {
				//ios
				map = ApkUtils.readIPA(urlPath);
				if (!"-1".equals(map.get("code").toString())){
					map.put("platform", "APP_IOS");
				}
			}
			if ("-1".equals(map.get("code").toString())){
				return Result.error(map.get("error").toString()+"请输入正确的链接。");
			}
			return Result.successMsg("根据下载链接获取应用包名成功", map);
		}catch (Exception e){
			log.error("根据下载链接获取应用包名异常",e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}

	@ApiOperation(value="获取行动号召", notes="获取行动号召")
	@GetMapping(value = "/getAdActionText")
	public Result getAdActionText(@RequestParam(value = "accountId",required = false) String accountId,
								  @RequestParam(value = "landingType",required = false) String landingType,
								  @RequestParam(value = "advancedCreativeType",required = false) String advancedCreativeType) {
		try {
			if (Check.isNull(accountId)){
				return Result.errorMsg("请选择账户。");
			}
			if (Check.isNull(landingType)){
				return Result.errorMsg("投放内容不能为空");
			}
			return aiBytedanceAdvertiserStrategyService.getAdActionText(accountId,landingType,advancedCreativeType);
		}catch (Exception e){
			log.error("获取行动号召异常",e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}

	@ApiOperation(value="获取定向包", notes="获取定向包")
	@GetMapping(value = "/getAdAudiencePackage")
	public Result getAdAudiencePackage(@RequestParam(value = "accountId",required = false) String accountId,
									   @RequestParam(value = "landingType",required = false) String landingType,
									   @RequestParam(value = "deliveryRange",required = false) String deliveryRange) {
		try {
			if (Check.isNull(accountId)){
				return Result.errorMsg("请选择账户。");
			}
			// 默认 定向包
			Result resultDefault = aiBytedanceAdvertiserStrategyService.getAdAudiencePackage(accountId,landingType,"DEFAULT");
			//穿山甲定向包
			Result resultUnion = aiBytedanceAdvertiserStrategyService.getAdAudiencePackage(accountId,landingType,"UNION");
			List listDefault = (List) resultDefault.getResult();
			List listUnion = (List) resultUnion.getResult();
			listDefault.addAll(listUnion);
			return Result.successMsg("获取定向包成功。",listDefault);
		}catch (Exception e){
			log.error("获取定向包异常",e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}

	@ApiOperation(value="获取人群包列表信息", notes="获取人群包列表信息")
	@GetMapping(value = "/getDMPCustomAudience")
	public Result getDMPCustomAudience(@RequestParam(value = "accountId",required = false) String accountId) {
		try {
			if (Check.isNull(accountId)){
				return Result.errorMsg("请选择账户。");
			}
			return aiBytedanceAdvertiserStrategyService.getDMPCustomAudience(accountId);
		}catch (Exception e){
			log.error("获取人群包列表异常",e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}

	@ApiOperation(value="创建定向包", notes="创建定向包")
	@PostMapping(value = "/createAudiencePackage")
	public Result createAudiencePackage(@RequestParam("accountId") String accountId) {
		try {
			return aiBytedanceAdvertiserStrategyService.createAudiencePackage(accountId);
		}catch (Exception e){
			log.error("创建定向包异常",e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}


	@ApiOperation(value="获取橙子建站站点列表", notes="获取橙子建站站点列表")
	@GetMapping(value = "/getChengZiSite")
	public Result getChengZiSite(@RequestParam("accountId") String accountId) {
		try {
			return aiBytedanceAdvertiserStrategyService.getChengZiSite(accountId);
		}catch (Exception e){
			log.error("获取橙子建站站点列表异常",e);
			return Result.error("请求失败，请联系开发人员!");
		}
	}








}
