package cn.quantgroup.xyqb.service.wechat.impl;

import cn.quantgroup.xyqb.Constants;
import cn.quantgroup.xyqb.entity.WechatUserInfo;
import cn.quantgroup.xyqb.event.WechatBindEvent;
import cn.quantgroup.xyqb.exception.WechatRelateUserException;
import cn.quantgroup.xyqb.model.JsonResult;
import cn.quantgroup.xyqb.model.webchat.*;
import cn.quantgroup.xyqb.repository.IWeChatInfoRelationRepository;
import cn.quantgroup.xyqb.repository.IWeChatUserRepository;
import cn.quantgroup.xyqb.service.http.IHttpService;
import cn.quantgroup.xyqb.service.wechat.IWechatFollowService;
import cn.quantgroup.xyqb.service.wechat.IWechatService;
import cn.quantgroup.xyqb.util.GcodeUtils;
import cn.quantgroup.xyqb.util.ValidationUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.ImmutableMap;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * Created by Miraculous on 2017/1/19.
 */
@Slf4j
@Service
public class WechatFollowServiceImpl implements IWechatFollowService {
    private static final String WECHAT_FOLLOW_TOKEN_KEY_PREFIX = "wechatFollow:token:";
    @Value("${wechat.appid}")
    private String appId;
    @Value("${wechat.secret}")
    private String secret;

    @Value("${qywechat.corpid}")
    private String corpid;
    @Value("${qywehcat.secret}")
    private String qySecret;

    // 部门
    @Value("${qywehcat.departmentId}")
    private Integer departmentId;

    private String accessTokenUrl;

    private String userListUrl;

    private String qyAccessTokenUrl;

    private String departmentUserListUrl;

    private String customerInfoListBatchUrl;

    // 消息中心
    private String msgEnterpriseToken;


    @Resource
    private IHttpService httpService;

    @Resource
    private IWeChatInfoRelationRepository weChatInfoRelationRepository;

    @Autowired
    @Qualifier("stringRedisTemplate")
    private RedisTemplate<String, String> redisTemplate;

    @Value("${mo-msg.http}")
    private String msgCenter;

    @Resource
    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    // 公众号
    private final Integer WECHAT_ACCOUNT = 1;

    //企业微信
    private final Integer ENTERPRISE_WECHAT = 2;

    // 公众号类型
    private final String WECHAT_XYQB = "xyqb";

    // 游标值
    private String cursorValue = "";

    @PostConstruct
    private void init() {
        // 公众号
        accessTokenUrl = String.format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", appId, secret);
        userListUrl = "https://api.weixin.qq.com/cgi-bin/user/get?access_token=%s&next_openid=%s";
        // 企业微信
        qyAccessTokenUrl = String.format("https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s", corpid, qySecret);
        // 成员列表
        departmentUserListUrl = "https://qyapi.weixin.qq.com/cgi-bin/user/simplelist?access_token=%s&department_id=%s&fetch_child=1";
        //批量获取客户详情
        customerInfoListBatchUrl = "https://qyapi.weixin.qq.com/cgi-bin/externalcontact/batch/get_by_user?access_token=%s";

        // 消息中心获取企业微信Token
        msgEnterpriseToken = String.format("%s/middle_office/token/enterprise?corpId=%s", msgCenter, corpid);

    }

    @Override
    public AccessTokenResponse getToken() {
        try {
            String response = httpService.get(accessTokenUrl);
            if (StringUtils.isEmpty(response)) {
                return null;
            }
            AccessTokenResponse accessTokenResponse = JSONObject.parseObject(response,
                    AccessTokenResponse.class);
            if (accessTokenResponse == null) {
                return null;
            }
            accessTokenResponse.setInitialTime(System.currentTimeMillis() - Constants.MILLIS_OF_TEN_SECOND);
            redisTemplate.opsForValue().set(WECHAT_FOLLOW_TOKEN_KEY_PREFIX, JSONObject.toJSONString(accessTokenResponse), accessTokenResponse.getExpiresIn() + Constants.THOUSAND_SECOND, TimeUnit.SECONDS);
            return accessTokenResponse;
        } catch (Exception ex) {
            return null;
        }
    }

    @Override
    public JsonResult executeWechatFollowStatus(String nextOpenId, String period) {
        AccessTokenResponse token = getToken();
        String userListUrlFormat = String.format(userListUrl, token.getAccessToken(), nextOpenId);
        try {
            String response = httpService.get(userListUrlFormat);
            if (response != null) {
                WechatUserListResponse wechatUserListResponse = JSONObject.parseObject(response, WechatUserListResponse.class);
                if (wechatUserListResponse.getErrcode() == null && wechatUserListResponse.getCount() > 0) {
                    nextOpenId = wechatUserListResponse.getNext_openid();
                    List<String> opendIdList = wechatUserListResponse.getData().get("openid");
                    if (!opendIdList.isEmpty()) {
                        String[] openIds = opendIdList.toArray(new String[0]);
                        String openIdStrs = String.join("\',\'", openIds);
                        openIdStrs = "\'" + openIdStrs + "\'";
                        // 添加公众号数据
                        String sql = String.format("INSERT INTO wechat_info_relation(`user_id`, `open_id`, `union_id`, `type`, `task_period`)  SELECT `user_id`, `open_id`, `union_id`, '%s', %s from wechat_userinfo where app_name='%s' and user_id is not null and `open_id` IN (%s)", WECHAT_ACCOUNT, period, WECHAT_XYQB, openIdStrs);
                        jdbcTemplate.update(sql);
                    }
                    if (nextOpenId != "") {
                        executeWechatFollowStatus(nextOpenId, period);
                    }
                    return JsonResult.buildSuccessResult("", opendIdList);
                } else {
                    return null;
                }
            }
        } catch (Exception ex) {
            log.error("同步微信公众号数据失败--{}", ex.getMessage());
            return null;
        }
        return null;


    }

    @Override
    public void executeTask() {
        // 初始化任务数据
//        initTask();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYYMMdd");
        String period = simpleDateFormat.format(new Date());

        // 微信公众号关注数据更新
        executeWechatFollowStatus("", period);
        // 企业微信关注数据更新
        executeEnterpriseFollowStatus("", period);
    }

    @Override
    public Object findByUnionIdsToUserIds(List<String> unionIds, String period) {
        return weChatInfoRelationRepository.findByUnionIdInAndTaskPeriodAndType(unionIds, period, ENTERPRISE_WECHAT);
    }

    private JsonResult executeEnterpriseFollowStatus(String s, String period) {
        try {

//            String response = httpService.get(qyAccessTokenUrl);
            String response = httpService.get(msgEnterpriseToken);
            if (StringUtils.isEmpty(response)) {
                log.info("请求消息中心企业微信Token为空---{}", response);
                return null;
            }
            Map<String, Object> tokenReponseMap = JSONObject.parseObject(response, Map.class);
            String token = tokenReponseMap.get("data").toString();
            if (token != null && !"".equals(token)) {
                String deparmentList = String.format(departmentUserListUrl, token, departmentId);
                String departmentRep = httpService.get(deparmentList);
                DepartmentListResponse departmentListResponse = JSONObject.parseObject(departmentRep, DepartmentListResponse.class);
                if (!departmentListResponse.getUserlist().isEmpty()) {
                    List<String> userIdList = departmentListResponse.getUserlist().stream().map(DepartmentInfoResponse::getUserid).collect(Collectors.toList());
                    System.out.println(userIdList);
                    if (!userIdList.isEmpty()) {
                        // 批量查询客户详情
                        batchQueryCustomerDetailInfo2(token, userIdList, "", period);
                    }
                }
            }
        } catch (Exception e) {
            log.error("同步企业微信数据失败--{}", e.getMessage());
            return null;
        }

        return null;
    }

    private JsonResult batchQueryCustomerDetailInfo(String accessToken, List<String> userIdList, String cursor, String period) {
        // 查询客户详情
        HashMap<String, Object> parameters = new HashMap<>();
        parameters.put("userid_list", userIdList);
        parameters.put("cursor", cursor);
        parameters.put("limit", "100");
        String customerInfoUrl = String.format(customerInfoListBatchUrl, accessToken);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(customerInfoUrl, parameters, String.class); //提交的body内容为user对象，请求的返回的body类型为String
        log.info("batchQueryCustomerDetailInfo--customerInfoUrl:{}, parameters:{}", customerInfoUrl, parameters);
        CustomerListResponse customerListResponse = JSONObject.parseObject(responseEntity.getBody(), CustomerListResponse.class);
        if (customerListResponse.getErrcode() == 0) {
            // 获取所有unionId
            List<String> unionIdAll = customerListResponse.getExternal_contact_list().stream().map(a -> a.getExternalContact().getUnionid()).collect(Collectors.toList());
            if (!unionIdAll.isEmpty()) {
                String[] unionIds = unionIdAll.toArray(new String[0]);
                String unionIdStrs = String.join("\',\'", unionIds);
                unionIdStrs = "\'" + unionIdStrs + "\'";
//                String sql = String.format("INSERT INTO wechat_enterprise(`unionid`) values ('%s')", String.join(",", unionIdAll));
                String sql = String.format("INSERT INTO wechat_info_relation(`user_id`, `open_id`, `union_id`, `type`, `task_period`)  SELECT `user_id`, `open_id`, `union_id`, '%s', %s from wechat_userinfo where  user_id is not null and `union_id` IN (%s)", ENTERPRISE_WECHAT, period, unionIdStrs);
                jdbcTemplate.update(sql);
            }

            // 根据unionid 添加现有指定信息
            // 判断nextCursor不为空，继续获取更多客户
            log.info("customerListResponse--{}", JSONObject.toJSONString(customerListResponse));
            if (!"".equals(customerListResponse.getNextCursor()) && !customerListResponse.getExternal_contact_list().isEmpty()) {
                batchQueryCustomerDetailInfo(accessToken, userIdList, customerListResponse.getNextCursor(), period);
            }
            return JsonResult.buildSuccessResult();
        } else {
            batchQueryCustomerDetailInfo(accessToken, userIdList, customerListResponse.getNextCursor(), period);
        }
        return JsonResult.buildSuccessResult();
    }

    private JsonResult batchQueryCustomerDetailInfo2(String accessToken, List<String> userIdList, String cursor, String period) {
        // 查询客户详情
        HashMap<String, Object> parameters = new HashMap<>();
        parameters.put("userid_list", userIdList);
        parameters.put("cursor", cursor);
        parameters.put("limit", "100");
        String customerInfoUrl = String.format(customerInfoListBatchUrl, accessToken);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(customerInfoUrl, parameters, String.class); //提交的body内容为user对象，请求的返回的body类型为String
        log.info("batchQueryCustomerDetailInfo--customerInfoUrl:{}, parameters:{}", customerInfoUrl, parameters);
        CustomerListResponse customerListResponse = JSONObject.parseObject(responseEntity.getBody(), CustomerListResponse.class);
        if (customerListResponse.getErrcode() == 0) {
            // 获取所有unionId
            List<String> unionIdAll = customerListResponse.getExternal_contact_list().stream().map(a -> a.getExternalContact().getUnionid()).collect(Collectors.toList());
            if (!unionIdAll.isEmpty()) {
                String[] unionIds = unionIdAll.toArray(new String[0]);
                String unionIdStrs = String.join("\',\'", unionIds);
                unionIdStrs = "\'" + unionIdStrs + "\'";
//                String sql = String.format("INSERT INTO wechat_enterprise(`unionid`) values ('%s')", String.join(",", unionIdAll));
                String sql = String.format("INSERT INTO wechat_info_relation(`user_id`, `open_id`, `union_id`, `type`, `task_period`)  SELECT `user_id`, `open_id`, `union_id`, '%s', %s from wechat_userinfo where  user_id is not null and `union_id` IN (%s)", ENTERPRISE_WECHAT, period, unionIdStrs);
                jdbcTemplate.update(sql);
            }

            // 根据unionid 添加现有指定信息
            // 判断nextCursor不为空，继续获取更多客户
            log.info("customerListResponse--{}", JSONObject.toJSONString(customerListResponse));
            cursorValue = customerListResponse.getNextCursor();
            while (!"".equals(cursorValue)) {
                batchQueryCustomerDetailFor(accessToken, userIdList, cursorValue, period);
            }
//            if (!"".equals(customerListResponse.getNextCursor()) && !customerListResponse.getExternal_contact_list().isEmpty()) {
//                batchQueryCustomerDetailInfo(accessToken, userIdList, customerListResponse.getNextCursor(), period);
//            }
            return JsonResult.buildSuccessResult();
        } else {
            batchQueryCustomerDetailFor(accessToken, userIdList, customerListResponse.getNextCursor(), period);
        }
        return JsonResult.buildSuccessResult();
    }

    private void batchQueryCustomerDetailFor(String accessToken, List<String> userIdList, String cursor, String period) {
        // 查询客户详情
        HashMap<String, Object> parameters = new HashMap<>();
        parameters.put("userid_list", userIdList);
        parameters.put("cursor", cursor);
        parameters.put("limit", "100");
        String customerInfoUrl = String.format(customerInfoListBatchUrl, accessToken);
        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> responseEntity = restTemplate.postForEntity(customerInfoUrl, parameters, String.class); //提交的body内容为user对象，请求的返回的body类型为String
        log.info("batchQueryCustomerDetailInfo--customerInfoUrl:{}, parameters:{}", customerInfoUrl, parameters);
        CustomerListResponse customerListResponse = JSONObject.parseObject(responseEntity.getBody(), CustomerListResponse.class);
        if (customerListResponse.getErrcode() == 0) {
            // 获取所有unionId
            List<String> unionIdAll = customerListResponse.getExternal_contact_list().stream().map(a -> a.getExternalContact().getUnionid()).collect(Collectors.toList());
            if (!unionIdAll.isEmpty()) {
                String[] unionIds = unionIdAll.toArray(new String[0]);
                String unionIdStrs = String.join("\',\'", unionIds);
                unionIdStrs = "\'" + unionIdStrs + "\'";
//                String sql = String.format("INSERT INTO wechat_enterprise(`unionid`) values ('%s')", String.join(",", unionIdAll));
                String sql = String.format("INSERT INTO wechat_info_relation(`user_id`, `open_id`, `union_id`, `type`, `task_period`)  SELECT `user_id`, `open_id`, `union_id`, '%s', %s from wechat_userinfo where  user_id is not null and `union_id` IN (%s)", ENTERPRISE_WECHAT, period, unionIdStrs);
                jdbcTemplate.update(sql);
            }

            // 根据unionid 添加现有指定信息
            // 判断nextCursor不为空，继续获取更多客户
            log.info("customerListResponse--{}", JSONObject.toJSONString(customerListResponse));
            cursorValue = customerListResponse.getNextCursor();
        }
    }


    private void initTask() {
        try {
            // 获取最大微信微信息ID
            log.info("微信同步公众号新增数据开始--");
            String querySql = "SELECT MAX(`wechat_userinfo_id`) as maxid FROM wechat_info_relation";
            Integer maxId = jdbcTemplate.queryForObject(querySql, Integer.class);
            System.out.println(maxId);
            if (maxId == null) {
                maxId = 0;
            }
            // 同步新增微信公众号数据（app_name 为 xyqb 并且有open_id和union_id)
            String sql = String.format("INSERT INTO wechat_info_relation(`wechat_userinfo_id`, `user_id`, `open_id`, `union_id`)  SELECT id, user_id, open_id, open_id from wechat_userinfo where id>%s and `open_id` is not null", maxId);
            jdbcTemplate.update(sql);
            log.info("微信同步公众号新增数据完成--");
            // 修改当前所有关注状态为 0 表示未关注
            log.info("修改微信关注状态开始--");
            String updateSql = "UPDATE wechat_info_relation set is_follow_wechat=0, is_follow_enterprise_wechat=0";
            jdbcTemplate.update(updateSql);
            log.info("修改微信关注状态完成--");
        } catch (Exception e) {
            log.error("微信公众号与企业微信关注情况任务失败---{}", e.getMessage());
        }
    }
}
