package org.jeecg.modules.ctop.controller;

import cn.com.ctop.common.module.entity.CtopOauthToken;
import cn.com.ctop.common.module.entity.SysDepart;
import cn.com.ctop.common.module.entity.SysUser;
import cn.com.ctop.common.module.entity.UserAllocation;
import cn.com.ctop.common.module.mapper.UserAllocationMapper;
import cn.com.ctop.common.module.service.IBindAccountAuthService;
import cn.com.ctop.common.module.service.ICtopOauthTokenService;
import cn.com.ctop.common.module.service.ISysDepartService;
import cn.com.ctop.common.module.service.ISysUserService;
import cn.com.ctop.common.module.utils.BytedanceInterfaceConstant;
import cn.com.ctop.common.module.utils.Check;
import cn.com.ctop.common.module.utils.HttpUtils;
import cn.com.ctop.common.module.utils.KuaishouInterfaceConstant;
import cn.com.ctop.common.module.utils.PropertiesUtils;
import cn.com.ctop.kuaishou.modules.ai.service.IKuaishouAppPackageService;
import cn.com.ctop.kuaishou.modules.batch.service.IKuaishouInterfaceService;
import cn.com.ctop.kuaishou.modules.material.entity.KuaishouAccessToken;
import cn.com.ctop.kuaishou.modules.material.entity.KuaishouResultToken;
import cn.com.ctop.toutiao.modules.material.service.IByteDanceAdvertiserDataService;
import cn.com.ctop.toutiao.modules.report.service.IReportService;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.system.util.JwtUtil;
import org.jeecg.common.util.RedisUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@RestController
public class CallbackController {
    @Autowired
    private ISysUserService sysUserService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private ISysDepartService sysDepartService;
    @Autowired
    private IKuaishouInterfaceService kuaishouInterfaceService;
    @Autowired
    private IBindAccountAuthService bindAccountAuthService;
    @Resource
    private UserAllocationMapper allocationMapper;
    @Autowired
    private ICtopOauthTokenService ctopOauthTokenService;
    @Autowired
    private IByteDanceAdvertiserDataService advertiserDataService;
    @Autowired
    private IReportService reportService;
    @Autowired
    private IKuaishouAppPackageService kuaishouAppPackageService;

    @GetMapping("/qywexin")
    public void qywexin(HttpServletRequest request,
                        HttpServletResponse response,
                        @RequestParam("code") String code,
                        @RequestParam("state") String state) throws IOException {
        System.err.println("code:" + code);
        System.err.println("state:" + state);
        response.sendRedirect(state + "?code=" + code);
    }

    /**
     * 用户信息
     *
     * @param sysUser
     * @param result
     * @return
     */
    private Result<JSONObject> userInfo(SysUser sysUser, Result<JSONObject> result) {
        String syspassword = sysUser.getPassword();
        String username = sysUser.getUsername();
        // 生成token
        String token = JwtUtil.sign(username, syspassword);
        redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
        // 设置超时时间
        redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);

        // 获取用户部门信息
        JSONObject obj = new JSONObject();
        List<SysDepart> departs = sysDepartService.queryUserDeparts(sysUser.getId());
        obj.put("departs", departs);
        if (departs == null || departs.isEmpty()) {
            obj.put("multi_depart", 0);
        } else if (departs.size() == 1) {
            sysUserService.updateUserDepart(username, departs.get(0).getOrgCode());
            obj.put("multi_depart", 1);
        } else {
            obj.put("multi_depart", 2);
        }
        obj.put("token", token);
        obj.put("userInfo", sysUser);
        result.setResult(obj);
        result.success("登录成功");
        return result;
    }

    /**
     * @param request
     * @param response
     * @param authCode
     * @param state
     * @return
     */
    @GetMapping("/kuaishou")
    public String kuaishouCallback(HttpServletRequest request, HttpServletResponse response, @RequestParam("auth_code") String authCode, @RequestParam("state") String state) {
        try {
            JSONObject json = JSONObject.parseObject(state);
            if (Check.isNull(json)) {
                throw new Exception("回调信息为空");
            }
            log.info("快手授权返回信息：{}", json);
            log.info("快手授权返回oauthCode：{}", authCode);
            Integer agentType = json.getInteger("agentType");
            Long appId = json.getLong("appId");
            if (StringUtils.isNotBlank(authCode)) {
                KuaishouResultToken accessToken = kuaishouInterfaceService.getAccessToken(authCode, appId);
                if (accessToken.getCode() != 0) {
                    throw new Exception("快手回调token返回错误");
                }
                KuaishouAccessToken token = accessToken.getData();
                if (token != null) {
                    Long accountId = token.getAccountId();
                    if (Check.isNull(accountId)) {
                        return "授权绑定失败！";
                    }

                    Map<String, Object> advertiseBaseInfoMap = kuaishouInterfaceService.advertiserInfo(accountId, token.getAccessToken());
                    if ((Integer) advertiseBaseInfoMap.get("code") != 0) {
                        return "授权绑定失败，失败原因:" + advertiseBaseInfoMap.get("message");
                    }
                    String advertiserId = json.getString("advertiserId");
                    //指定分配人姓名
                    String userName = json.getString("userName");

                    // 媒体类型： 1 头条 2 快手
                    String mediaId = json.getString("mediaId");
                    //创建人
                    String userId = json.getString("userId");
                    Long projectId = json.getLong("projectId");
                    String authBeginTime = json.getString("authBeginTime");
                    BigDecimal warningProportion = json.getBigDecimal("WarningProportion");
                    BigDecimal warningAmount = json.getBigDecimal("WarningAmount");
                    String systemType = json.getString("systemType");


                    Integer autoDelivery = json.getInteger("autoDelivery");
                    String materialTypeStr = json.getString("materialType");
                    //物料类型，0-不同步，1应用包，（2人群包，3定向包）
                    JSONArray materialTypeArr = json.getJSONArray("materialType");

                    CtopOauthToken topOauthToken = new CtopOauthToken();
                    topOauthToken.setId(String.valueOf(accountId));
                    topOauthToken.setAppId(json.getLong("appId"));
                    topOauthToken.setAccountId(accountId);
                    topOauthToken.setMediaId("2");
                    topOauthToken.setAdvertiserId(advertiserId);
                    topOauthToken.setAgentType(agentType);
                    topOauthToken.setAccessToken(token.getAccessToken());
                    long accessTokenExpireIn = token.getAccessTokenExpiresIn() * 1000L;
                    long now = System.currentTimeMillis();
                    Date accessTokenExpireInDate = new Date(now + accessTokenExpireIn);
                    topOauthToken.setAccessTokenExpiresIn(accessTokenExpireInDate);
                    topOauthToken.setRefreshToken(token.getRefreshToken());
                    long refreshTokenExpireIn = token.getRefreshTokenExpiresIn() * 1000L;
                    Date refreshTokenExpireInDate = new Date(now + refreshTokenExpireIn);
                    topOauthToken.setRefreshTokenExpiresIn(refreshTokenExpireInDate);
                    topOauthToken.setUpdateTime(new Date());
                    ctopOauthTokenService.saveOrUpdate(topOauthToken);
                    QueryWrapper<UserAllocation> userAllocationQueryWrapper = new QueryWrapper<>();
                    userAllocationQueryWrapper.eq("account_id", accountId);
                    userAllocationQueryWrapper.eq("media_id", 2);
                    userAllocationQueryWrapper.orderByDesc("create_time");
                    userAllocationQueryWrapper.last("limit 1");
                    UserAllocation checkUserAllocation = allocationMapper.selectOne(userAllocationQueryWrapper);
                    if (!Check.isNull(checkUserAllocation)) {
                        return "授权失败，该账号已被：" + checkUserAllocation.getUserName() + " 绑定！";
                    }
                    UserAllocation userAllocation = new UserAllocation();
                    userAllocation.setUserName(userName);
                    userAllocation.setUserId(userId);
                    userAllocation.setAdvertiserId(advertiserId);
                    userAllocation.setSystemType(systemType);
                    // 获取快手昵称
                    userAllocation.setAuthName((String) advertiseBaseInfoMap.get("userName"));
                    if (null != authBeginTime && !authBeginTime.trim().equals("")) {
                        userAllocation.setAuthBeginTime(authBeginTime);
                    }
                    userAllocation.setMediaId(mediaId);
                    userAllocation.setAccountId(accountId);
                    userAllocation.setProjectId(projectId);
                    userAllocation.setWarningProportion(warningProportion);
                    userAllocation.setWarningAmount(warningAmount);
                    userAllocation.setCreateTime(new Date());
                    userAllocation.setUpdateTime(new Date());
                    //自动投放，0关闭，1开启

                    userAllocation.setAutoDelivery(autoDelivery);
                    userAllocation.setMaterialType(materialTypeStr);
                    allocationMapper.deleteById(userAllocation.getId());
                    Map<String, Object> deleteUserMap = new HashMap<>();
                    deleteUserMap.put("advertiser_id", advertiserId);
                    deleteUserMap.put("account_id", accountId);
                    allocationMapper.deleteByMap(deleteUserMap);
                    log.info("待创建账户信息：{}", userAllocation.toString());
                    int i = allocationMapper.insert(userAllocation);
                    if (i > 0) {
                        log.info("同步分配用户表完成,task_id:{},accountId:{}", state, accountId);
                    }
                    Integer materialType = materialTypeArr.getInteger(0);
                    //账号绑定
                    bindAccountAuthService.addBindAccount(accountId, KuaishouInterfaceConstant.LOGIN_TYPE_KUAISHOU, advertiserId);
                    Thread t = new Thread() {
                        @Override
                        public void run() {
                            try {
                                kuaishouInterfaceService.loadKuaishouDataSingle(topOauthToken);

                                if (!Check.isNull(materialType) && materialType != 0) {
                                    synchronMaterials(materialType, accountId, projectId);
                                }
                            } catch (ParseException e) {
                                e.printStackTrace();
                            }
                        }
                    };
                    t.start();
                }
                return "授权绑定成功";
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "授权绑定失败！";
    }

    private void synchronMaterials(Integer materialType, Long accountId, Long projectId) {
        if (materialType == 1) {
            JSONArray accountIds = new JSONArray();
            accountIds.add(accountId);
            //1 有效项目模板
            List<Long> ids = kuaishouAppPackageService.queryByAppVersion(projectId, null, 1);
            JSONObject data = new JSONObject();
            data.put("accountIds", accountIds);
            data.put("message", "授权同步应用");
            log.info("同步账户应用,应用模板={}", ids);
            if (!Check.isNull(ids)) {
                for (Long id : ids) {
                    data.put("id", id);
                }
            }
        }
    }

    @RequestMapping("/bytedance")
    public String bytedance(HttpServletRequest request,
                            HttpServletResponse response,
                            @RequestParam("auth_code") String authCode,
                            @RequestParam("state") String state) {

        if (StringUtils.isNotBlank(authCode)) {
            Map<String, Object> map = this.getByteDanceAccessToken(authCode, state);
            log.info("返回信息:{}", map.toString());
            return (String) map.get("desc");
        }
        return "授权绑定失败";
    }

    public Map<String, Object> getByteDanceAccessToken(String authCode, String state) {
        Map<String, Object> param = new HashMap<>();
        param.put("app_id", PropertiesUtils.getValue("bytedance_config", "bytedance_appid"));
        param.put("secret", PropertiesUtils.getValue("bytedance_config", "bytedance_secret"));
        param.put("grant_type", "auth_code");
        param.put("auth_code", authCode);
        log.info("authCode:{}", authCode);
        log.info("state:{}", state);
        Map<String, Object> returnMap = new HashMap<>();
        try {
            JSONObject json = JSONObject.parseObject(state);
            if (Check.isNull(json)) {
                throw new Exception("回调信息为空");
            }
            String result = HttpUtils.httpPostRequest(PropertiesUtils.getValue("bytedance_config", "bytedance_api_url") + BytedanceInterfaceConstant.AUTH_TOKEN, param, new HashMap<>());
            JSONObject resultObject = JSONObject.parseObject(result);
            log.info("返回信息：{}", resultObject);
            Integer code = resultObject.getInteger("code");
            String message = resultObject.getString("message");
            if (null == code || code != 0) {
                log.error("获取token失败,state:{},message:{}", state, message);
                throw new Exception("token返回码异常");
            }
            //广告主id
            String advertiserId = json.getString("advertiserId");
            // 媒体类型： 1 头条 2 快手
            String mediaId = json.getString("mediaId");

            //创建人
            String userId = json.getString("userId");
            //创建人
            String userName = json.getString("userName");
            String authBeginTime = json.getString("authBeginTime");
            Long projectId = json.getLong("projectId");
            BigDecimal warningProportion = json.getBigDecimal("WarningProportion");
            BigDecimal warningAmount = json.getBigDecimal("WarningAmount");
            JSONObject data = resultObject.getJSONObject("data");
            if (Check.isNull(data)) {
                returnMap.put("code", -1);
                returnMap.put("desc", "返回信息为空");
                return returnMap;

            }
            data.remove("advertiser_id");
            JSONArray advertiser_ids = data.getJSONArray("advertiser_ids");
            if (Check.isNull(advertiser_ids)) {
                returnMap.put("code", -1);
                returnMap.put("desc", "请选择需要授权的账号");
                return returnMap;

            }
            data.remove("advertiser_ids");
            StringBuilder text = new StringBuilder();
            for (int i = 0; i < advertiser_ids.size(); i++) {
                Long advertiser_id = advertiser_ids.getLong(i);
                JSONObject adJson = advertiserDataService.getAdvertiserList(data.getString("access_token"), advertiser_id);
                Integer returnCode = adJson.getInteger("code");
                if (returnCode == 0) {
                    JSONArray dataArr = adJson.getJSONArray("data");
                    if (!Check.isNull(dataArr)) {
                        for (int j = 0; j < dataArr.size(); j++) {
                            JSONObject dataJson = dataArr.getJSONObject(j);
                            Long advertiser_id1 = dataJson.getLong("advertiser_id");
                            data.put("advertiser_id", advertiser_id1);
                            CtopOauthToken token = new CtopOauthToken(advertiserId, data);
                            ctopOauthTokenService.saveOrUpdate(token);
                            //获取广告主信息
                            Map<String, Object> advertiserDataMap = advertiserDataService.getAdvertiserInfo(advertiser_id1 + "", data.getString("access_token"));
                            Boolean getSuccess = (Boolean) advertiserDataMap.get("success");
                            if (null == getSuccess || !getSuccess) {
                                log.info("获取广告主信息失败,accountId:{},message:{}", token.getAccountId(), (String) advertiserDataMap.get("message"));
                                text.append("账户id:" + advertiser_id + "，暂未获取数据权限，请检查账户")
                                        .append("<br/>");
                                continue;
                            }

                            Long accountId = token.getAccountId();
                            QueryWrapper<UserAllocation> userAllocationQueryWrapper = new QueryWrapper<>();
                            userAllocationQueryWrapper.eq("account_id", accountId);
                            userAllocationQueryWrapper.eq("media_id", 1);
                            userAllocationQueryWrapper.orderByDesc("create_time");
                            userAllocationQueryWrapper.last("limit 1");
                            UserAllocation checkUserAllocation = allocationMapper.selectOne(userAllocationQueryWrapper);
                            if (!Check.isNull(checkUserAllocation)) {
                                text.append("账户id:" + accountId + "，授权名称为：" + (String) advertiserDataMap.get("name") + "，绑定失败，失败原因：已被" + checkUserAllocation.getUserName() + "绑定。")
                                        .append("<br/>");
                                continue;
                            }
                            text.append("账户id:" + accountId + "，授权名称为：" + (String) advertiserDataMap.get("name") + "，绑定成功。").append("<br/>");
                            String systemType = json.getString("systemType");
                            UserAllocation userAllocation = new UserAllocation();
                            userAllocation.setUserId(userId);
                            userAllocation.setUserName(userName);
                            userAllocation.setAccountId(token.getAccountId());
                            userAllocation.setMediaId(mediaId);
                            userAllocation.setProjectId(projectId);
                            userAllocation.setSystemType(systemType);
                            userAllocation.setAuthName((String) advertiserDataMap.get("name"));
                            if (null != authBeginTime && !authBeginTime.trim().equals("")) {
                                userAllocation.setAuthBeginTime(authBeginTime);
                            }
                            userAllocation.setAdvertiserId(advertiserId);
                            userAllocation.setWarningProportion(warningProportion);
                            userAllocation.setWarningAmount(warningAmount);
                            userAllocation.setCreateTime(new Date());
                            userAllocation.setUpdateTime(new Date());
                            int g = allocationMapper.insert(userAllocation);
                            if (g > 0) {
                                log.info("同步分配用户表完成,task_id:{},accountId:{}", state, token.getAccountId());
                            }
                            //账号绑定
                            bindAccountAuthService.addBindAccount(token.getAccountId(), KuaishouInterfaceConstant.LOGIN_TYPE_BYTEDANCE, advertiserId);
                            new Thread(() -> reportService.loadBytedanceHistoryData(token)).start();
                        }

                    }

                } else {
                    data.put("advertiser_id", advertiser_id);
                    CtopOauthToken token = new CtopOauthToken(advertiserId, data);
                    ctopOauthTokenService.saveOrUpdate(token);
                    //获取广告主信息
                    Map<String, Object> advertiserDataMap = advertiserDataService.getAdvertiserInfo(advertiser_id + "", data.getString("access_token"));
                    Boolean getSuccess = (Boolean) advertiserDataMap.get("success");
                    if (null == getSuccess || !getSuccess) {
                        log.info("获取广告主信息失败,accountId:{},message:{}", token.getAccountId(), (String) advertiserDataMap.get("message"));
                        text.append("账户id:" + advertiser_id + "，暂未获取数据权限，请检查账户")
                                .append("<br/>");
                        continue;
                    }

                    Long accountId = token.getAccountId();
                    QueryWrapper<UserAllocation> userAllocationQueryWrapper = new QueryWrapper<>();
                    userAllocationQueryWrapper.eq("account_id", accountId);
                    userAllocationQueryWrapper.eq("media_id", 1);
                    userAllocationQueryWrapper.orderByDesc("create_time");
                    userAllocationQueryWrapper.last("limit 1");
                    UserAllocation checkUserAllocation = allocationMapper.selectOne(userAllocationQueryWrapper);
                    if (!Check.isNull(checkUserAllocation)) {
                        text.append("账户id:" + accountId + "，授权名称为：" + (String) advertiserDataMap.get("name") + "，绑定失败，失败原因：已被" + checkUserAllocation.getUserName() + "绑定。")
                                .append("<br/>");
                        continue;
                    }
                    text.append("账户id:" + accountId + "，授权名称为：" + (String) advertiserDataMap.get("name") + "，绑定成功。").append("<br/>");
                    String systemType = json.getString("systemType");
                    UserAllocation userAllocation = new UserAllocation();
                    userAllocation.setUserId(userId);
                    userAllocation.setUserName(userName);
                    userAllocation.setAccountId(token.getAccountId());
                    userAllocation.setMediaId(mediaId);
                    userAllocation.setProjectId(projectId);
                    userAllocation.setSystemType(systemType);
                    userAllocation.setAuthName((String) advertiserDataMap.get("name"));
                    if (null != authBeginTime && !authBeginTime.trim().equals("")) {
                        userAllocation.setAuthBeginTime(authBeginTime);
                    }
                    userAllocation.setAdvertiserId(advertiserId);
                    userAllocation.setWarningProportion(warningProportion);
                    userAllocation.setWarningAmount(warningAmount);
                    userAllocation.setCreateTime(new Date());
                    userAllocation.setUpdateTime(new Date());
                    int g = allocationMapper.insert(userAllocation);
                    if (g > 0) {
                        log.info("同步分配用户表完成,task_id:{},accountId:{}", state, token.getAccountId());
                    }
                    //账号绑定
                    bindAccountAuthService.addBindAccount(token.getAccountId(), KuaishouInterfaceConstant.LOGIN_TYPE_BYTEDANCE, advertiserId);
                    new Thread(() -> reportService.loadBytedanceHistoryData(token)).start();
                }


            }


            returnMap.put("code", 0);
            returnMap.put("desc", text.toString());

        } catch (
                Exception e) {
            e.printStackTrace();
            returnMap.put("code", -1);
            returnMap.put("desc", "回调token异常");
        }
        return returnMap;
    }

    @GetMapping("/kuaishou/agent")
    public String kuaishouAgent(@RequestParam("auth_code") String authCode, @RequestParam("state") String state) {
        if (StringUtils.isNotBlank(authCode)) {
            Map<String, Object> map = this.getKuaishouAgentAccessToken(authCode, state);
            log.info("返回信息:{}", map.toString());
            return (String) map.get("desc");
        }
        return "代理商授权绑定失败";
    }

    private Map<String, Object> getKuaishouAgentAccessToken(String authCode, String state) {
        return null;
    }


}
