package com.template.controller;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.util.StringUtil;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.template.annotation.PassToken;
import com.template.api.WechatScanLoginControllerAPI;
import com.template.common.constanst.Constanst;
import com.template.common.result.ResponseStatusEnum;
import com.template.common.utils.*;
import com.template.model.enumModel.eIdentityStatu;
import com.template.model.evaluate.student.SmartEvaluateStudent;
import com.template.model.evaluate.student.SmartSubjectManage;
import com.template.model.pojo.SmartAuthority;
import com.template.model.pojo.SmartDepartment;
import com.template.model.pojo.SmartUser;
import com.template.model.pojo.SmsCode;
import com.template.model.result.CommonResult;
import com.template.model.result.PageUtils;
import com.template.model.tongji.*;
import com.template.model.vo.AffiliateParentVo;
import com.template.model.vo.LoginVO;
import com.template.model.vo.WechatUserVo;
import com.template.model.weixin.AccessToken;
import com.template.model.weixin.HttpParame;
import com.template.model.weixin.WechatUserUnionID;
import com.template.services.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Title: WechatScanLoginController
 * Description: 微信扫码登录controller
 *
 * @author fengyong
 * @date 2018年9月7日
 */
@Controller
public class WechatScanLoginController implements WechatScanLoginControllerAPI {

    @Autowired
    private WechatScanLoginService wechatScanLoginService;
    @Autowired
    public SmartUserService smartUserService;
    @Autowired
    public SmartAuthorityService smartAuthorityService;
    @Autowired
    public SmartAuthorGroupService smartAuthorGroupService;
    @Autowired
    public SmartDepartmentService smartDepartmentService;
    @Autowired
    public SmsCodeService smsCodeService;

    /**
     * Title: list
     * Description: 重定向到微信扫码登录二维码页面
     * 此处显示要微信要扫描的二维码
     *
     * @param model
     * @return
     * @throws UnsupportedEncodingException
     */
    @Override
    @PassToken
    public String login(Model model) throws UnsupportedEncodingException {
        Map<String, String> wechatLoginUrl = wechatScanLoginService.wechatLoginUrl();
        String url = wechatLoginUrl.get("url");
        System.out.println(url);
        return "redirect:" + url;
    }

    /**
     * Title: callback
     * Description: 回调地址处理
     *
     * @param code
     * @param state
     * @return
     */
    @Override
    @PassToken
    public String callback(String code, String state) throws UnsupportedEncodingException {
        System.out.println(code + "=====" + state);
        if (code != null && state != null) {
            // 验证state为了用于防止跨站请求伪造攻击
            String decrypt = AesUtil.decrypt(AesUtil.parseHexStr2Byte(state), AesUtil.PASSWORD_SECRET_KEY, 16);
            if (!decrypt.equals(Constanst.PWD_MD5 + DateUtils.getYYYYMMdd())) {
                return "redirect:" + HttpParame.FRONT_URI + "/#/login?message=" + URLEncoder.encode("请勿非法进入", "UTF-8");
            }
            AccessToken access = wechatScanLoginService.getAccessToken(code);
            System.out.println("access:" + access);
            if (access != null) {
                String openid = access.getOpenid();
                System.out.println("openid: " + openid);
                SmartUser user = wechatScanLoginService.selectByOpenid(openid);
                if (user == null) {        /*不存在*/
                    return "redirect:" + HttpParame.FRONT_URI + "/#/login?message=" + URLEncoder.encode("请绑定信息", "UTF-8");
                } else {
                    String token = JWTUtil.getToken(user, null);
                    QueryWrapper<SmartAuthority> queryWrapper1 = new QueryWrapper<>();
                    queryWrapper1.eq("deleted", 0);
                    queryWrapper1.eq("user_id", user.getId());
                    List<SmartAuthority> query = smartAuthorityService.getAuthorByKey(queryWrapper1);
                    if (query.size() > 0) {
                        return "redirect:" + HttpParame.FRONT_URI + "/#/wanzai/home?token=" + token;
                    } else {
                        return "redirect:" + HttpParame.FRONT_URI + "/#/login?message=" + URLEncoder.encode("无登录权限", "UTF-8");
                    }
                }
            }
        }
        return null;
    }

    /**
     * Title: bindingUserMac2
     * Description: 跳转到绑定用户系统帐号页面
     *
     * @return
     */
    @Override
    @PassToken
    public String bindUserMac(String phone, String messageCode) throws UnsupportedEncodingException {
        if (StringUtils.isBlank(phone) || StringUtils.isBlank(messageCode)) {
            return "redirect:" + HttpParame.FRONT_URI + "/#/login?message=" + URLEncoder.encode("请输入信息", "UTF-8");
        }
        Map<String, String> wechatLoginUrl = wechatScanLoginService.wechatBindUrl(phone, messageCode);
        String url = wechatLoginUrl.get("url");
        System.out.println(url);
        return "redirect:" + url;
    }

    @Override
    @PassToken
    public String bindcallback(String code, String state, String phone, String messageCode) throws UnsupportedEncodingException {
        System.out.println(code + "===" + state + "==" + messageCode);
        if (code != null && state != null) {
            // 验证state为了用于防止跨站请求伪造攻击
            String decrypt = AesUtil.decrypt(AesUtil.parseHexStr2Byte(state), AesUtil.PASSWORD_SECRET_KEY, 16);
            if (!decrypt.equals(Constanst.PWD_MD5 + DateUtils.getYYYYMMdd())) {
                return "redirect:" + HttpParame.FRONT_URI + "/#/login?message=" + URLEncoder.encode("请勿非法进入", "UTF-8");
            }
            AccessToken access = wechatScanLoginService.getAccessToken(code);
            if (access != null) {
                String openid = access.getOpenid();
                QueryWrapper<SmsCode> queryWrapper1 = new QueryWrapper<>();
                queryWrapper1.eq("deleted", 0);
                queryWrapper1.eq("is_verify", 0);
                queryWrapper1.eq("phone_number", phone);
                queryWrapper1.eq("code", messageCode);
                queryWrapper1.ge("expiration_time", new Date());
                List<SmsCode> listc = smsCodeService.getSmsCodeByKey(queryWrapper1);
                if (listc.isEmpty()) {
                    return "redirect:" + HttpParame.FRONT_URI + "/#/login?message=" + URLEncoder.encode("验证码已失效", "UTF-8");
                }
                QueryWrapper<SmartUser> queryWrapper2 = new QueryWrapper<>();
                queryWrapper2.eq("deleted", 0);
                queryWrapper2.eq("phone", phone);
                List<SmartUser> userc = smartUserService.list(queryWrapper2);
                if (userc.isEmpty()) {
                    return "redirect:" + HttpParame.FRONT_URI + "/#/login?message=" + URLEncoder.encode("用户不存在", "UTF-8");
                }
                userc.get(0).setOpenId(openid);
                int m = wechatScanLoginService.updateSmartUser(userc.get(0));
                if (m > 0) {
                    String token = JWTUtil.getToken(userc.get(0), null);
                    QueryWrapper<SmartAuthority> queryWrapper3 = new QueryWrapper<>();
                    queryWrapper3.eq("deleted", 0);
                    queryWrapper3.eq("user_id", userc.get(0).getId());
                    List<SmartAuthority> query = smartAuthorityService.getAuthorByKey(queryWrapper3);
                    if (query.size() > 0) {
                        return "redirect:" + HttpParame.FRONT_URI + "/#/wanzai/home?token=" + token;
                    } else {
                        return "redirect:" + HttpParame.FRONT_URI + "/#/login?message=" + URLEncoder.encode("无登录权限", "UTF-8");
                    }
                }
            }
        }
        return "redirect:" + HttpParame.FRONT_URI + "/#/login?message=" + URLEncoder.encode("系统异常", "UTF-8");
    }

    @Override
    @PassToken
    public String insertMonthMeter(String month) {
        if (month == null) {
            month = TimeExchange2.getMonth();
        }
        wechatScanLoginService.insertMonthMeter(month);
        return "插入完毕";
    }

    @Override
    @PassToken
    public String insertDayMeter(String day) {
        if (day == null) {
            day = TimeExchange2.getDateStr();
        }
        wechatScanLoginService.insertDayMeter(day);
        return "插入完毕";
    }

    /**
     * Description: 用户类别统计
     */
    @Override
    @PassToken
    public CommonResult getUserIdTj() {
        List<Tj> list = wechatScanLoginService.getUserIdTj();
        return CommonResult.ok(list);
    }

    /**
     * Description: 用户总数
     */
    @Override
    @PassToken
    public CommonResult getUserIdTjt() {
        All list = wechatScanLoginService.getUserIdTjt();
        return CommonResult.ok(list);
    }

    /**
     * Description: 水表总计
     */
    @Override
    @PassToken
    public CommonResult getWaterTj() {
        DAll list = wechatScanLoginService.getWaterTj();
        return CommonResult.ok(list);
    }

    /**
     * Description: 电表总计
     */
    @Override
    @PassToken
    public CommonResult getElcTj() {
        DAll list = wechatScanLoginService.getElcTj();
        return CommonResult.ok(list);
    }

    /**
     * Description: 每月水费查询
     */
    @Override
    @PassToken
    public CommonResult getMonWater() throws ParseException {
        List<MonthMeterDetail> list = wechatScanLoginService.getMonWater();
        return CommonResult.ok(list);
    }

    /**
     * Description: 每月电费查询
     */
    @Override
    @PassToken
    public CommonResult getMonElc() throws ParseException {
        List<MonthMeterDetail> list = wechatScanLoginService.getMonElc();
        return CommonResult.ok(list);
    }

    /**
     * Description: 区域能耗统计
     */
    @Override
    @PassToken
    public CommonResult getMeterMonthPage(@RequestBody MeterMonthData meterMonthData, int currentPage, int pageCount) {
        PageHelper.startPage(currentPage, pageCount);
        PageInfo<MeterMonthData> list = wechatScanLoginService.getMeterMonthPage(meterMonthData);
        return CommonResult.ok(list);
    }

    /**
     * Description: 实时抄表
     */
    @Override
    @PassToken
    public CommonResult getMeterDayPage(@RequestBody MeterMonthData meterMonthData, int currentPage, int pageCount) {
        PageHelper.startPage(currentPage, pageCount);
        PageInfo<MeterMonthData> list = wechatScanLoginService.getMeterDayPage(meterMonthData);
        return CommonResult.ok(list);
    }

    /**
     * Description: 查轨迹
     */
    @Override
    @PassToken
    public CommonResult getPosition() {
        List<List<BigDecimal>> ld = RandomTrackAlgorithm.getPosition();
        return CommonResult.ok(ld);
    }

    @Override
    @PassToken
    public CommonResult vertify(String code) {
        if (StringUtils.isBlank(code)) {
            return CommonResult.fail("请传入code");
        }
        String url = "https://api.weixin.qq.com/sns/jscode2session?" +
                "appid=" + PropertiesUtil.getValue(HttpParame.APPIDX) +
                "&secret=" + PropertiesUtil.getValue(HttpParame.SECRETX) +
                "&js_code=" + code +
                "&grant_type=authorization_code";

        String json = HttpClientUtils.getInstance().sendHttpGet(url);
        Gson gson = new Gson();
        HashMap<String, String> userMap = gson.fromJson(json.toString(), new TypeToken<HashMap<String, String>>() {
        }.getType());
        String openid = "";
        try {
            openid = userMap.get("openid").toString();
        } catch (Exception e) {
            return CommonResult.fail("code异常");
        }
        QueryWrapper<SmartUser> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("deleted", 0);
        queryWrapper1.eq("is_cancel", 0);
        queryWrapper1.eq("x_open_id", openid);
        List<SmartUser> user = smartUserService.list(queryWrapper1);
        if (user.isEmpty()) {
            return CommonResult.fail("请绑定后再进入");
        }
        //部门数据集合
        List<SmartDepartment> departments = smartDepartmentService.list(null);

        long expired = 1000 * 60 * 60 * 24 * 365;
        String token = JWTUtil.getToken(user.get(0), expired);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("token", token);
        List<WechatUserVo> userDatas = new ArrayList<>();
        for (SmartUser su : user) {
            WechatUserVo userData = new WechatUserVo();
            userData.setId(su.getId());
            userData.setCardNo(su.getCardNo());
            userData.setTimeGroupId(su.getTimeGroupId());
            userData.setName(su.getName());
            userData.setIdentityId(su.getIdentityId());
            userData.setIdCard(su.getIdCard());
            userData.setSexId(su.getSexId());
            userData.setDepartmentId(su.getDepartmentId());

            Optional<SmartDepartment> department = departments.stream().filter(e -> e.getId().equals(su.getDepartmentId())).findFirst();
            if (department != null && department.isPresent()) {
                String departmentName = QueryParentDepartments(department.get().getParentId(), departments, null);
                userData.setDepartmentName(departmentName == null ? "" : departmentName + "/" + department.get().getName());
            }

            userData.setHeadImage(su.getHeadImage());
            userData.setGrade(su.getGrade());
            userData.setCollege(su.getCollege());
            userData.setSpeciality(su.getSpeciality());
            userData.setSchoolClass(su.getSchoolClass());
            userData.setCampus(su.getCampus());
            userData.setDormitoryNumber(su.getDormitoryNumber());
            userData.setPhone(su.getPhone());
            userData.setAffiliate(su.getAffiliate());
            //查找关联人
            if (su.getIdentityId().intValue() == eIdentityStatu.Student.getValue()) {//学生
                List<AffiliateParentVo> parents = smartUserService.queryAffiliateParents(su.getId());
                if (parents != null && parents.size() > 0) {
                    String affiliateStr = StringUtils.join(parents.stream().map(AffiliateParentVo::getName).collect(Collectors.toList()), ",");
                    userData.setAffiliateName(affiliateStr);
                }
            } else if (su.getIdentityId().intValue() == eIdentityStatu.Parent.getValue()) {//家长
                if (su.getAffiliate() != null) {
                    List<String> affiliates = Arrays.asList(su.getAffiliate().split(","));
                    List<SmartUser> childs = smartUserService.getSmartUserIds(affiliates);
                    String affiliateStr = StringUtils.join(childs.stream().map(SmartUser::getName).collect(Collectors.toList()), ",");
                    userData.setAffiliateName(affiliateStr);
                }
            }
            //关联人名称用逗号隔开

            userData.setTitle(su.getTitle());
            userData.setAddress(su.getAddress());
            userData.setNation(su.getNation());
            userData.setOfStudent(su.getOfStudent());
            userData.setGraduate(su.getGraduate());
            userData.setDuties(su.getDuties());
            userData.setIsPush(su.getIsPush());
            userData.setIsCancel(su.getIsCancel());
            userData.setOpenId(su.getOpenId());
            userData.setXOpenId(su.getXOpenId());
            userData.setGzhOpenId(su.getGzhOpenId());
            userData.setXwStudentUid(su.getXwStudentUid());
            userData.setBsStudentNo(su.getBsStudentNo());
            userData.setXwTeacherCode(su.getXwTeacherCode());
            userData.setBsStaffCode(su.getBsStaffCode());
            userDatas.add(userData);
        }

        jsonObject.put("user", userDatas);
        jsonObject.put("userhead", AesUtils.encrypt(String.valueOf(user.get(0).getId())));

        return CommonResult.ok(jsonObject.toString());
    }

    /**
     * 根据父级ID获取父级数据
     *
     * @param parentID 子级ID
     * @param lists    数据集合
     * @return
     */
    private static String QueryParentDepartments(Integer parentID, List<SmartDepartment> lists, String departmentStr) {
        Optional<SmartDepartment> data = lists.stream().filter(e -> e.getId().equals(parentID)).findFirst();

        if (data != null && data.isPresent()) {
            departmentStr = departmentStr == null ? data.get().getName() : data.get().getName() + "/" + departmentStr;
            departmentStr = QueryParentDepartments(data.get().getParentId(), lists, departmentStr);
        }

        return departmentStr;
    }

    @Override
    @PassToken
    public CommonResult sendMessage(String phone) {
        QueryWrapper<SmartUser> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("deleted", 0);
        queryWrapper1.eq("phone", phone);
        queryWrapper1.eq("is_cancel", 0);
        List<SmartUser> list = smartUserService.list(queryWrapper1);
        if (list.isEmpty()) {
            return CommonResult.fail("该手机无权限登录");
        }
        QueryWrapper<SmsCode> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("deleted", 0);
        queryWrapper2.eq("is_verify", 0);
        queryWrapper2.eq("phone_number", phone);
        queryWrapper2.ge("expiration_time", new Date());
        List<SmsCode> listc = smsCodeService.getSmsCodeByKey(queryWrapper2);
        if (!listc.isEmpty()) {
            return CommonResult.fail("操作频繁，请稍后再试");
        }
        String code = GetVertifyCode.getRandomNumCode(6);
        SmsCode smsCode = new SmsCode();
        smsCode.setId(UUIDUtil.generateID());
        smsCode.setPhoneNumber(phone);
        smsCode.setCode(code);
        long time = new Date().getTime() + 300000L;
        smsCode.setExpirationTime(new Date(time));
        smsCode.setIsVerify("0");
        smsCode.setDeleted(0);
        int m = smsCodeService.insertSmsCode(smsCode);
        if (m > 0) {
            String message = SendSms.sendSms(phone, code);
            if (message.contains("success")) {
                return CommonResult.ok("发送成功");
            }
        }
        return CommonResult.fail("操作失败");
    }

    @Override
    @PassToken
    public CommonResult vertifyMessage(String phone, String code, String wxcode) {
        QueryWrapper<SmsCode> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("deleted", 0);
        queryWrapper1.eq("is_verify", 0);
        queryWrapper1.eq("phone_number", phone);
        queryWrapper1.eq("code", code);
        queryWrapper1.ge("expiration_time", new Date());
        List<SmsCode> listc = smsCodeService.getSmsCodeByKey(queryWrapper1);
        if (listc.isEmpty()) {
            return CommonResult.ok("验证码已失效");
        }
        if (StringUtils.isBlank(wxcode)) {
            return CommonResult.fail("请传入wxcode");
        }
        String url = "https://api.weixin.qq.com/sns/jscode2session?" +
                "appid=" + PropertiesUtil.getValue(HttpParame.APPIDX) +
                "&secret=" + PropertiesUtil.getValue(HttpParame.SECRETX) +
                "&js_code=" + wxcode +
                "&grant_type=authorization_code";

        String json = HttpClientUtils.getInstance().sendHttpGet(url);
        System.out.println(json);
        Gson gson = new Gson();
        HashMap<String, String> userMap = gson.fromJson(json.toString(), new TypeToken<HashMap<String, String>>() {
        }.getType());
        String openid = "";
        try {
            openid = userMap.get("openid").toString();
        } catch (Exception e) {
            return CommonResult.fail("wxcode异常");
        }
        QueryWrapper<SmartUser> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.eq("deleted", 0);
        queryWrapper2.eq("phone", phone);
        List<SmartUser> user = smartUserService.list(queryWrapper2);
        if (user.isEmpty()) {
            return CommonResult.fail("该用户不存在");
        }
        user.get(0).setXOpenId(openid);
        smartUserService.updateSmartUser(user.get(0));
        long expired = 1000 * 60 * 60 * 24 * 365;
        String token = JWTUtil.getToken(user.get(0), expired);
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("token", token);
        jsonObject.put("user", user.get(0));
        jsonObject.put("userhead", AesUtils.encrypt(String.valueOf(user.get(0).getId())));
        return CommonResult.ok(jsonObject);
    }
}
