package com.fs.app.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 cn.hutool.core.date.DateTime;
import com.alibaba.fastjson.JSON;
import com.fs.app.annotation.Login;
import com.fs.app.param.LoginMaWxParam;
import com.fs.app.utils.JwtUtils;
import com.fs.common.core.domain.R;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.utils.IpUtil;
import com.fs.common.utils.ServletUtils;
import com.fs.company.domain.Company;
import com.fs.company.domain.CompanyUser;
import com.fs.company.service.ICompanyDeptService;
import com.fs.company.service.ICompanyService;
import com.fs.company.service.ICompanyUserService;
import com.fs.core.config.WxMaConfiguration;
import com.fs.course.config.CourseMaConfig;
import com.fs.course.domain.FsUserCompanyUser;
import com.fs.course.service.IFsUserCompanyUserService;
import com.fs.his.domain.FsUser;
import com.fs.his.domain.FsUserWx;
import com.fs.his.service.IFsUserService;
import com.fs.his.service.IFsUserWxService;
import com.fs.system.domain.SysConfig;
import com.fs.system.mapper.SysConfigMapper;
import com.fs.wx.miniapp.config.WxMaProperties;
import io.jsonwebtoken.Claims;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.Objects;

import static com.fs.his.utils.PhoneUtil.encryptPhone;

@Api("微信小程序相关接口（暂废弃，后面再删除）")
@RestController
@RequestMapping(value = "/app/wx/miniapp")
@Slf4j
public class WxCompanyUserController extends AppBaseController {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    JwtUtils jwtUtils;
    @Autowired
    private ICompanyUserService companyUserService;
    @Autowired
    private IFsUserService userService;
    @Autowired
    private ICompanyService companyService;
    @Autowired
    private IFsUserCompanyUserService userCompanyUserService;
    @Autowired
    private IFsUserWxService fsUserWxService;

    @ApiOperation("小程序-授权登录")
    @PostMapping("/loginByMa")
    public R login(@RequestBody LoginMaWxParam param) {
        log.info("=====================进入小程序授权登录, 入参: {}", param);
        if (StringUtils.isBlank(param.getCode())) {
            return R.error("code不存在");
        }

        // 特殊（需求设计：需要根据公司是否开启黑名单来设置会员初始化的状态）
        Company company = companyService.selectCompanyById(param.getCompanyId());
        if (company==null || company.getStatus()==0){
            return R.error("注册失败团队已停用，或不存在！");
        }

        // 根据销售后台设置的  是否需要单独注册会员 来判断是否需要设置销售的值
        CompanyUser companyUser = companyUserService.selectCompanyUserById(param.getCompanyUserId());;
        if(companyUser == null || companyUser.getStatus().equals("1")){
            return R.error("注册失败客服已停用，或不存在！");
        }
//        if (company.getCourseMiniAppId() == null) {
//            return R.error("小程序参数错误!");
//        }
//        if (!param.getAppId().equals(company.getCourseMiniAppId())){
//            return R.error("无权限，");
//        }

        final WxMaService wxService = WxMaConfiguration.getMaService(param.getAppId());
        try {
            WxMaJscode2SessionResult session = wxService.getUserService().getSessionInfo(param.getCode());
            this.logger.info(session.getSessionKey());
            this.logger.info(session.getOpenid());
            this.logger.info(session.getUnionid());
            if (StringUtils.isEmpty(session.getOpenid())){
                return R.error("登陆失败，openid未授权，请稍后再试!");
            }

            if (param.getAuthType() == 2 && StringUtils.isEmpty(session.getUnionid())){
                return R.error("未绑定开发平台,请联系管理员!");
            }

            // 手机号信息
            WxMaPhoneNumberInfo phoneNoInfo = new WxMaPhoneNumberInfo();;
            if (param.getAuthType()==1){
                phoneNoInfo = wxService.getUserService().getPhoneNoInfo(session.getSessionKey(), param.getEncryptedData(), param.getIv());
                if (StringUtils.isEmpty(phoneNoInfo.getPhoneNumber())){
                    return R.error("授权失败，请联系客服！");
                }
            }

            FsUser user = getUserByAuthType(param, wxService, session, phoneNoInfo);

            // 3. 处理用户注册或更新
            String ip = IpUtil.getRequestIp();
            user = handleUserRegisterOrUpdate(user, param, session, phoneNoInfo, company, companyUser, ip);

            FsUserCompanyUser userCompanyUser = userCompanyUserService.selectByUserIdAndProjectId(user.getUserId(), param.getProjectId());
            if (Objects.nonNull(userCompanyUser) && !param.getCompanyUserId().equals(userCompanyUser.getCompanyUserId())){
                return R.error(500, "该用户("+user.getUserId() + ")已成为其他销售会员");
            }

            // 4. 处理用户与小程序的绑定
            handleFsUserWx(user, param, session);

            log.info("保存成功的用户信息user: {}, 用户id: {},小程序AppId:{}", user, user.getUserId(), param.getAppId());
            String token = jwtUtils.generateToken(user.getUserId());
            // 返回TOKEN和user
            return R.ok("登录成功").put("token", token).put("user", user);
        } catch (WxErrorException e) {
            this.logger.error(e.getMessage(), e);
            return R.error("授权失败," + e.getMessage());
        }
    }

    /**
     * 根据authType获取用户信息
     */
    private FsUser getUserByAuthType(LoginMaWxParam param, WxMaService wxService, WxMaJscode2SessionResult session, WxMaPhoneNumberInfo phoneNoInfo) throws WxErrorException {
        FsUser user = null;
        if (param.getAuthType() == 1) {
            user = userService.selectFsUserByPhone(encryptPhone(phoneNoInfo.getPhoneNumber()));
        } else {
            // unionid判定唯一
            if (StringUtils.isNotEmpty(session.getUnionid())) {
                user = userService.selectFsUserByUnionId(session.getUnionid());
            }
        }
        return user;
    }

    /**
     * 处理用户注册或更新
     */
    private FsUser handleUserRegisterOrUpdate(FsUser user, LoginMaWxParam param, WxMaJscode2SessionResult session, WxMaPhoneNumberInfo phoneNoInfo, Company company, CompanyUser companyUser, String ip) {
        if (user == null) {
            return createUser(param, session, phoneNoInfo, company, companyUser);
        } else {
            return updateUser(user, param, session, phoneNoInfo, company, companyUser);
        }
    }

    /**
     * 新增用户
     */
    private FsUser createUser(LoginMaWxParam param, WxMaJscode2SessionResult session, WxMaPhoneNumberInfo phoneNoInfo, Company company, CompanyUser companyUser) {
        FsUser user = new FsUser();
        user.setStatus((company != null ? company.getFsUserIsDefaultBlack() : 0) == 1 ? 0 : 1);
        user.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
        user.setCreateTime(new Date());
        if (param.getAuthType() == 1 && phoneNoInfo != null) {
            user.setPhone(phoneNoInfo.getPhoneNumber());
        }
        userService.insertFsUser(user);

        if((companyUser.getIsAllowedAllRegister() == null || companyUser.getIsAllowedAllRegister() == 1)
                && companyUser.getIsNeedRegisterMember() != null && companyUser.getIsNeedRegisterMember() != 1){
            int defaultStatus = (company != null ? company.getFsUserIsDefaultBlack() : 0) == 1 ? 0 : 1;
            userCompanyUserService.bindRelationship(user.getUserId(), param.getProjectId(), companyUser.getCompanyId(), companyUser.getUserId(), defaultStatus);
        }
        return user;
    }

    /**
     * 修改用户
     */
    private FsUser updateUser(FsUser user, LoginMaWxParam param, WxMaJscode2SessionResult session, WxMaPhoneNumberInfo phoneNoInfo, Company company, CompanyUser companyUser) {
        FsUser userMap = new FsUser();
        userMap.setUserId(user.getUserId());
        userMap.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
        userMap.setUpdateTime(new DateTime());
        if (param.getAuthType() == 1 && phoneNoInfo != null) {
            userMap.setPhone(phoneNoInfo.getPhoneNumber());
        }

        userService.updateFsUser(userMap);
        return userMap;
    }

    /**
     * 处理用户与小程序的绑定
     */
    private void handleFsUserWx(FsUser user, LoginMaWxParam param, WxMaJscode2SessionResult session) {
        if (user == null) return;
        // 尝试更新
        boolean updated = fsUserWxService.lambdaUpdate()
                .eq(FsUserWx::getFsUserId, user.getUserId())
                .eq(FsUserWx::getAppId, param.getAppId())
                .eq(FsUserWx::getOpenId, session.getOpenid())
                .set(FsUserWx::getCompanyId, param.getCompanyId())
                .set(FsUserWx::getUnionId, session.getUnionid() == null ? "" : session.getUnionid())
                .set(FsUserWx::getUpdateTime, new Date())
                .update();

        // 如果更新失败（记录不存在），则插入
        if (!updated) {
            FsUserWx fsUserWx = new FsUserWx();
            fsUserWx.setType(1);
            fsUserWx.setFsUserId(user.getUserId());
            fsUserWx.setCompanyId(param.getCompanyId());
            fsUserWx.setAppId(param.getAppId());
            fsUserWx.setOpenId(session.getOpenid());
            fsUserWx.setUnionId(session.getUnionid() == null ? "" : session.getUnionid());
            fsUserWx.setCreateTime(new Date());
            fsUserWx.setUpdateTime(new Date());
            fsUserWxService.save(fsUserWx);
        }
    }
}
