package com.huiju.estateagents.controller;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaUserInfo;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.huiju.estateagents.base.BaseController;
import com.huiju.estateagents.base.ResponseBean;
import com.huiju.estateagents.center.sysUser.entity.SysToken;
import com.huiju.estateagents.center.sysUser.service.ISysTokenService;
import com.huiju.estateagents.center.taUser.entity.TaUser;
import com.huiju.estateagents.center.taUser.service.ITaUserService;
import com.huiju.estateagents.common.CommConstant;
import com.huiju.estateagents.common.WxUtils;
import com.huiju.estateagents.entity.*;
import com.huiju.estateagents.event.EventBus;
import com.huiju.estateagents.mapper.TaOrgCityMapper;
import com.huiju.estateagents.mapper.TaShareMapper;
import com.huiju.estateagents.service.*;
import com.huiju.estateagents.common.JWTUtils;
import com.huiju.estateagents.third.entity.TaThirdPartyMiniappConfig;
import com.huiju.estateagents.third.service.ITaThirdPartyMiniappConfigService;
import me.chanjar.weixin.common.error.WxErrorException;
import net.bytebuddy.asm.Advice;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
@RequestMapping("/api/wx")
public class MiniAppController extends BaseController {

    private Logger logger = LoggerFactory.getLogger(MiniAppController.class);

    @Autowired
    private ITaPersonService taPersonService;

    @Autowired
    private IMiniAppService miniAppService;

    @Autowired
    private ITaRecommendCustomerService taRecommendCustomerService;

    @Resource
    private ApplicationContext applicationContext;

    @Autowired
    private ITaOrgService taOrgService;

    @Autowired
    private ISysTokenService sysTokenService;

    @Autowired
    private ITaMiniappService taMiniappService;

    @Autowired
    private ITaSharePersonFromService taSharePersonFromService;

    @Autowired
    private ITaBuildingDynamicService buildingDynamicService;

    @Autowired
    private ITaNewsService newsService;

    @Autowired
    private ITaUserService userService;

    @Autowired
    private ITaPersonBuildingService personBuildingService;

    @Autowired
    public ITaThirdPartyMiniappConfigService iTaThirdPartyMiniappConfigService;

    @Autowired
    private ITaCustomImgService iTaCustomImgService;

    @Autowired
    public ITdPointsRulesService iTdPointsRulesService;

    @Autowired
    public ITaMiniappService iTaMiniappService;

    @Autowired
    public TaOrgCityMapper taOrgCityMapper;

    @Autowired
    public ITdCityService iTdCityService;

    /**
     * 验证接入
     */
    @GetMapping(value = "/", produces = "text/plain;charset=utf-8")
    public String access(@RequestParam(name = "signature", required = false) String signature,
                         @RequestParam(name = "timestamp", required = false) String timestamp,
                         @RequestParam(name = "nonce", required = false) String nonce,
                         @RequestParam(name = "echostr", required = false) String echostr) {
        return echostr;
    }


    /**
     * 小程序数据预拉取 https://developers.weixin.qq.com/miniprogram/dev/framework/ability/pre-fetch.html
     *
     * @param appid
     * @param timestamp
     * @param token
     * @param code
     * @param path
     * @param query
     * @param scene
     * @return
     */
    @GetMapping("/preload")
    public ResponseBean getPreloadData(
            @RequestParam(name = "appid") String appid,
            @RequestParam(name = "timestamp") Long timestamp,
            String token,
            String code,
            String path,
            String query,
            Integer scene
    ) {
        // 获取小程序信息
        TaMiniapp taMiniapp = iTaMiniappService.getInfoWithTpls(appid);
        if (null == taMiniapp) {
            return ResponseBean.error("当前 appid 未在系统内注册", ResponseBean.ERROR_ILLEGAL_PARAMS);
        }

        // 获取组织信息
        TaOrg taOrg = taOrgService.getById(taMiniapp.getOrgId());
        if (null == taOrg) {
            return ResponseBean.error("当前 appid 未设置对应组织", ResponseBean.ERROR_UNAVAILABLE);
        }

        // 获取城市列表
        QueryWrapper<TaOrgCity> queryCity = new QueryWrapper<>();
        queryCity.eq("id", taOrg.getOrgId());
        queryCity.eq("status", CommConstant.STATUS_NORMAL);
        List<TaOrgCity> taOrgCityList = taOrgCityMapper.selectList(queryCity);

        // 获取默认扩展设置
        QueryWrapper<TaCustomImg> queryExt = new QueryWrapper<>();
        queryExt.eq("org_id", taOrg.getOrgId());
        queryExt.eq("status", CommConstant.STATUS_NORMAL);
        List<TaCustomImg> taCustomImg = iTaCustomImgService.list(queryExt);

        return ResponseBean.success(new HashMap<String, Object>() {{
            put("miniapp", taMiniapp);
            put("org", taOrg);
            put("cityList", taOrgCityList);
            put("customImg", taCustomImg);
        }});
    }

    /**
     * 登陆接口
     */
    @PostMapping("/login")
    public ResponseBean login(
            String code,
            @RequestParam(required = false) String from,
            @RequestParam(required = false) String recommender,
            @RequestParam(required = false) String targetId,
            @RequestParam(required = false) String lon,
            @RequestParam(required = false) String lat,
            HttpServletRequest request) {
        String appid = request.getHeader("appid");

        if (StringUtils.isBlank(code)) {
            return ResponseBean.error("参数 code 不能为空", ResponseBean.ERROR_ILLEGAL_PARAMS);
        }
        if (StringUtils.isBlank(appid)) {
            return ResponseBean.error("Header 参数 appid 不能为空", ResponseBean.ERROR_ILLEGAL_PARAMS);
        }

        // 校验服务过期日期等
        ResponseBean checkResp = checkMiniappStatus(appid);
        if (checkResp != null) {
            return checkResp;
        }

        try {
            TaMiniapp miniapp = taMiniappService.getById(appid);
            WxMaJscode2SessionResult session = miniAppService.getSessionInfo(code, appid);
            Integer orgId = miniapp.getOrgId();
            Map<String, Object> miniResp = new HashMap<>();
            miniResp.put("openid", session.getOpenid());
            miniResp.put("sessionKey", session.getSessionKey());
            miniResp.put("unionid", session.getUnionid());
            miniResp.put("name", miniapp.getName());
            miniResp.put("tpls", miniAppService.getTpls(appid));
            miniResp.put("fddServerHost", miniapp.getFddServerHost());

            // 2020年3月30日 与曹建芳讨论 去掉此规则
//            //如果是分享进来且没有进入过小程序，给分享人发放积分
//            QueryWrapper<TaPerson> personQueryWrapper = new QueryWrapper<>();
//            personQueryWrapper.eq("mini_openid", session.getOpenid());
//            personQueryWrapper.eq("org_id", orgId);
//            int count = taPersonService.count(personQueryWrapper);

            TaPerson taPerson = taPersonService.newPersonByOpenid(session.getOpenid(), orgId);
            if (null == taPerson) {
                return ResponseBean.error("发生未知错误", ResponseBean.ERROR_UNAVAILABLE);
            }

            Map<Object, Object> map = new HashMap<>();
            map.put("openId", session.getOpenid());
            map.put("orgId", orgId);
            map.put("personId", taPerson.getPersonId());
            miniResp.put("token", JWTUtils.newTokenByMap(map));
            if (StringUtils.isEmpty(taPerson.getFromCode())) {
                taPerson.setFromCode(from);
            }
            if (StringUtils.isEmpty(taPerson.getRecommendPerson())) {
                taPerson.setRecommendPerson(recommender);
                TaPerson type = taPersonService.getById(recommender);
                if (null != type) {
                    if (!StringUtils.isEmpty(type.getPersonType())) {
                        taPerson.setRecommendPersonType(type.getPersonType());
                    }
                }
            }
            taPerson.setMiniappId(appid);
            taPersonService.updateById(taPerson);

            // 增加积分线程
            ExecutorService threadPool = Executors.newCachedThreadPool();
            threadPool.execute(() -> {
//                if (null != from && from.contains("share") && !com.huiju.estateagents.common.StringUtils.isEmpty(recommender) && count > 0) {
                if (null != from && from.contains("share") && !com.huiju.estateagents.common.StringUtils.isEmpty(recommender)) {
                    // 校验是否点击过此人的分享
                    boolean checkPoint = checkSharePersonFrom(from, taPerson.getPersonId(), targetId, orgId);
                    if (checkPoint) {
                        // 添加积分
                        applicationContext.publishEvent(new EventBus(recommender, EventBus.EventType.SharePosterAll, orgId));
                    }
                }
            });

            if (StringUtils.isNotBlank(from) && StringUtils.isNotBlank(recommender) && StringUtils.isNotBlank(targetId)) {
                TaSharePersonFrom taSharePersonFrom = new TaSharePersonFrom();
                TaPerson recommenderPerson = taPersonService.getById(recommender);
                taSharePersonFrom.setCreateDate(LocalDateTime.now());
                taSharePersonFrom.setOrgId(orgId);
                taSharePersonFrom.setPersonId(taPerson.getPersonId());
                taSharePersonFrom.setSharePersonType(recommenderPerson.getPersonType());
                taSharePersonFrom.setTargetId(targetId);
                taSharePersonFrom.setTargetType(from);
                if (CommConstant.PERSON_REALTY_CONSULTANT.equals(recommenderPerson.getPersonType())) {
                    taSharePersonFrom.setSharePerson(recommenderPerson.getUserId().toString());
                } else {
                    taSharePersonFrom.setSharePerson(recommenderPerson.getPersonId());
                }
                QueryWrapper<TaSharePersonFrom> sharePersonFromQueryWrapper = new QueryWrapper<>();
                sharePersonFromQueryWrapper.eq("person_id", taPerson.getPersonId());
                if (from.equals("dynamic_share")) { // activity_share
                    //产品不认了
                    taSharePersonFrom.setStatus(CommConstant.STATUS_NORMAL);
                    TaBuildingDynamic buildingDynamic = buildingDynamicService.getById(targetId);
                    taSharePersonFrom.setBuildingId(buildingDynamic.getBuildingId());
                    sharePersonFromQueryWrapper.eq("building_id", buildingDynamic.getBuildingId());
                } else {
                    taSharePersonFrom.setStatus(CommConstant.STATUS_NORMAL);
                }
                if (from.contains("card")) {
                    // 因为targetId 是 personId ，需要查询出 userId
                    TaPerson person = taPersonService.getById(targetId);

                    QueryWrapper<TaPersonBuilding> personBuildingQueryWrapper = new QueryWrapper<>();
                    personBuildingQueryWrapper.eq("user_id", person.getUserId());
                    TaPersonBuilding personBuilding = personBuildingService.getOne(personBuildingQueryWrapper);
                    taSharePersonFrom.setBuildingId(personBuilding.getBuildingId());
                    sharePersonFromQueryWrapper.eq("building_id", personBuilding.getBuildingId());
                } else if (from.contains("news")) {
                    TaNews news = newsService.getById(targetId);
                    taSharePersonFrom.setBuildingId(news.getBuildingId());
                    sharePersonFromQueryWrapper.eq("building_id", news.getBuildingId());
                } else if (from.contains("building")) {
                    taSharePersonFrom.setBuildingId(targetId);
                    sharePersonFromQueryWrapper.eq("building_id", targetId);
                }
                Integer isFirstTime = taSharePersonFromService.count(sharePersonFromQueryWrapper);
                if (isFirstTime > 0) {
                    taSharePersonFrom.setIsFirstTime(false);
                } else {
                    taSharePersonFrom.setIsFirstTime(true);
                }
                taSharePersonFromService.save(taSharePersonFrom);
            }

            taPerson.setPassword(null);

            // 获取其余信息
            Map<String, Object> extraInfo = taPersonService.getExtraInfo(taPerson.getPersonId());
            // 所有人员都返回 org yansen 2019-11-13 19:56:18
//            if (CommConstant.PERSON_REALTY_CONSULTANT.equals(taPerson.getPersonType())){
            QueryWrapper<TaOrg> orgQueryWrapper = new QueryWrapper<>();
            orgQueryWrapper.eq("org_id", orgId);
            TaOrg org = taOrgService.getOne(orgQueryWrapper);
            taPerson.setOrg(org);
//            }
            Map<String, Object> result = new HashMap<>();
            result.put("miniApp", miniResp);
            result.put("person", taPerson);
            result.put("extraInfo", extraInfo);
            result.put("miniAuthorized", null != taPerson.getAvatarurl() && taPerson.getAvatarurl().indexOf("wx.qlogo.cn") > 0);

            //返回是否授权标识
            QueryWrapper<TaCustomImg> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("org_id", orgId);
            queryWrapper.eq("img_type", "auth");
            List<TaCustomImg> taCustomImgs = iTaCustomImgService.list(queryWrapper);
            result.put("avatarAuth", CollectionUtils.isEmpty(taCustomImgs) ? false : "1".equals(taCustomImgs.get(0).getImgUrl()) ? true : false);

            String token = (String) miniResp.get("token");
            sysTokenService.saveToken(token);

            //把積分規則返回給小程序
            QueryWrapper<TdPointsRules> tdPointsRulesQueryWrapper = new QueryWrapper<>();
            tdPointsRulesQueryWrapper.eq("org_id", orgId);
            List<TdPointsRules> rulesPointList = iTdPointsRulesService.list(tdPointsRulesQueryWrapper);
            result.put("rulesPointList", rulesPointList);

            // 定位城市
            String location = null == lon ? null : lon + "," + lat;
            TdCity tdCity = iTdCityService.getLocationCity(location, orgId, taPerson.getPersonId());
            result.put("city", tdCity);

            return ResponseBean.success(result);
        } catch (WxErrorException e) {
            System.err.println(e.getError());
            return ResponseBean.error("解析小程序 code 失败", ResponseBean.ERROR_UNAVAILABLE);
        }
    }

    private ResponseBean checkMiniappStatus(String appid) {
        TaUser taUser = userService.getAdminByAppID(appid);

        if (null == taUser) {
            return ResponseBean.error("系统尚未添加管理员, 请联系相关人员", ResponseBean.ERROR_UNAVAILABLE);
        }

        if (null == taUser.getExpDate() || LocalDateTime.now().isAfter(taUser.getExpDate())) {
            return ResponseBean.error("系统服务已到期或者尚未设置到期日期", ResponseBean.ERROR_UNAVAILABLE);
        }

        if (null == taUser.getStatus() || CommConstant.STATUS_NORMAL != taUser.getStatus()) {
            return ResponseBean.error("系统服务被停止或者出现异常", ResponseBean.ERROR_UNAVAILABLE);
        }

        return null;
    }

    private boolean checkSharePersonFrom(String from, String personId, String targetId, Integer orgId) {
        QueryWrapper<TaSharePersonFrom> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("target_type", from);
        queryWrapper.eq("person_id", personId);
        queryWrapper.eq("target_id", targetId);
        queryWrapper.eq("org_id", orgId);
        List<TaSharePersonFrom> list = taSharePersonFromService.list(queryWrapper);
        if (list.size() > 0) {
            return false;
        }
        return true;
    }

    /**
     * 登陆接口
     */
    @PostMapping("/logout")
    public ResponseBean logout(HttpServletRequest request) {
        String openid = getOpenId(request);
        List<TaPerson> persons = taPersonService.getPersonsByOpenId(openid);
        if (null == persons || persons.size() == 0) {
            return ResponseBean.success("");
        }

        return ResponseBean.success("");
    }


    /**
     * 获取用户信息, 并写入内部人员表
     */
    @PostMapping("/signup")
    public ResponseBean info(@RequestBody String paramStr, HttpServletRequest request) {
        String appid = request.getHeader("appid");
        TaPerson person = null;
        TaMiniapp miniapp = taMiniappService.getById(appid);
        if (null == paramStr || "".equals(paramStr.trim()) || "{}".equals(paramStr.trim())) {
            String openid = getOpenId(request);
            List<TaPerson> taPersons = taPersonService.getPersonsByOpenId(openid);
            if (null == taPersons || taPersons.size() != 1) {
                return ResponseBean.error("验证人员信息失败", ResponseBean.ERROR_UNAVAILABLE);
            }
            person = taPersons.get(0);
        } else {

            JSONObject params = JSONObject.parseObject(paramStr);
            if (null == params) {
                return ResponseBean.error("校验参数失败", ResponseBean.ERROR_ILLEGAL_PARAMS);
            }

            String sessionKey = params.getString("sessionKey");
            String signature = params.getString("signature");
            String rawData = params.getString("rawData");
            String encryptedData = params.getString("encryptedData");
            String iv = params.getString("iv");

            // 用户信息校验
            if (!miniAppService.checkUserInfo(sessionKey, rawData, signature, appid)) {
                return ResponseBean.error("校验参数失败", ResponseBean.ERROR_ILLEGAL_PARAMS);
            }

            // 解密用户信息
            WxMaUserInfo userInfo = miniAppService.getUserInfo(sessionKey, encryptedData, iv, appid);

            // 更新或保存用户信息
            person = taPersonService.mergePersonWxInfo(userInfo);
            if (null == person) {
                return ResponseBean.error("发生未知错误", ResponseBean.ERROR_UNAVAILABLE);
            }
            taPersonService.upDatePersonCityToId(person.getPersonId());
        }

        // 获取其余信息
        Map<String, Object> extraInfo = taPersonService.getExtraInfo(person.getPersonId());
        person.setPassword(null);

        Map<String, Object> result = new HashMap<>();
        result.put("person", person);
        result.put("extraInfo", extraInfo);
        result.put("miniApp", miniapp);

        return ResponseBean.success(result);
    }

    /**
     * 获取用户绑定手机号信息
     */
    @PostMapping("/userPhone")
    public ResponseBean phone(@RequestBody String paramStr, HttpServletRequest request) {
        String appid = request.getHeader("appid");
        JSONObject params = JSONObject.parseObject(paramStr);
        if (null == params) {
            return ResponseBean.error("校验参数失败", ResponseBean.ERROR_ILLEGAL_PARAMS);
        }

        String sessionKey = params.getString("sessionKey");
        String encryptedData = params.getString("encryptedData");
        String iv = params.getString("iv");
        String buildingId = params.getString("buildingId");

        // 解密
        WxMaPhoneNumberInfo phoneNoInfo = miniAppService.getPhoneNoInfo(sessionKey, encryptedData, iv, appid);

        // 更新用户绑定手机
        String openid = getOpenId(request);
        Integer orgId = getOrgId(request);
        taPersonService.updatePersonPhone(openid, phoneNoInfo.getPhoneNumber(), buildingId, orgId);
        List<TaPerson> taPersons = taPersonService.getPersonsByOpenId(openid);
        if (null == taPersons || taPersons.size() != 1) {
            return ResponseBean.error("验证人员信息失败", ResponseBean.ERROR_UNAVAILABLE);
        }
        TaPerson person = taPersons.get(0);
        QueryWrapper<TaRecommendCustomer> cus = new QueryWrapper<>();
        cus.eq("org_id", orgId);
        cus.eq("phone", phoneNoInfo.getPhoneNumber());
        cus.orderByDesc("create_date");
        List<TaRecommendCustomer> customer = taRecommendCustomerService.list(cus);
        if (customer.size() > 0) {
            for (int i = 0; i < customer.size(); i++) {
                customer.get(i).setPersonId(person.getPersonId());
                customer.get(i).setPicture(person.getAvatarurl());
                customer.get(i).setCountry(person.getCountry());
                customer.get(i).setCity(person.getCity());
                customer.get(i).setProvince(person.getProvince());
            }
//            TaRecommendCustomer customers = customer.get(0);

            if (!taRecommendCustomerService.updateBatchById(customer)) {
                return ResponseBean.error("验证人员信息失败", ResponseBean.ERROR_UNAVAILABLE);
            }
//            if(null != customers.getRecommendPerson()&&!StringUtils.isEmpty(customers.getRecommendPerson())&& StringUtils.isEmpty(person.getRecommendPerson())){
//                person.setRecommendPerson(customers.getRecommendPerson());
//                person.setRecommendPerson(customers.getRecommendPerson());
//                TaPerson recommender = taPersonService.getById(customers.getRecommendPerson());
//                if(null != recommender.getPersonType()&&!StringUtils.isEmpty(recommender.getPersonType())){
//                    person.setRecommendPersonType(recommender.getPersonType());
//                }
//            }

//            QueryWrapper<TaCustomerPerson> customerPersonQueryWrapper = new QueryWrapper<>();
//            customerPersonQueryWrapper.eq("person_id",person.getPersonId());
//            customerPersonQueryWrapper.eq("customer_id",customers.getCustomerId());
//            List<TaCustomerPerson> list = taCustomerPersonService.list(customerPersonQueryWrapper);
//            if(list.size()<=0){
//                taCustomerPersonService.insertBean(person.getPersonId(),customers.getCustomerId());
//            }
        }
//        else{
//            TaRecommendCustomer taRecommendCustomer = new TaRecommendCustomer();
//            taRecommendCustomer.setPersonId(person.getPersonId());
//            taRecommendCustomer.setPicture(person.getAvatarurl());
//            taRecommendCustomer.setCountry(person.getCountry());
//            taRecommendCustomer.setCity(person.getCity());
//            taRecommendCustomer.setProvince(person.getProvince());
//            taRecommendCustomer.setVerifyStatus(CommConstant.VERIFY_AGREE);
//            taRecommendCustomer.setOrgId(getOrgId(request));
//            taRecommendCustomer.setEntryType(CommConstant.ENTRY_VOLUNTEER);
//            taRecommendCustomer.setSex(Integer.getInteger(person.getGender()));
//
//        }
        return ResponseBean.success(phoneNoInfo);
    }

    /**
     * 生成二维码
     *
     * @return
     */
    @PostMapping("/qrcode")
    public ResponseBean qrcode(@RequestBody String paramsStr, HttpServletRequest request) {
        String appid = request.getHeader("appid");
        return miniAppService.getQrCode(paramsStr, appid);
    }

    /**
     * 获取二维码参数
     *
     * @param serialNo
     * @return
     */
    @GetMapping("/qrcode/scene/{serialNo}")
    public ResponseBean getScene(@PathVariable String serialNo) {
        try {
            Integer id = Integer.valueOf(serialNo);
            TaMiniappQrcode qrcode = miniAppService.getQrCodeBySerialNo(id);
            if (null == qrcode) {
                return ResponseBean.error("不存在的二维码参数", HttpStatus.SC_BAD_REQUEST);
            }

            return ResponseBean.success(qrcode.getQrParams());
        } catch (Exception e) {
            e.printStackTrace();
            return ResponseBean.error("获取二维码参数失败: " + e.getMessage(), HttpStatus.SC_INTERNAL_SERVER_ERROR);
        }
    }

    public Integer getOrgId(HttpServletRequest request) {

        Map map = JWTUtils.getUserIdAndOrgId(request);
        if (null != map && null != map.get("orgId")) {
            return Integer.valueOf(map.get("orgId").toString());
        }

        return null;
    }
}
