package org.springblade.modules.auth.endpoint;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.extern.slf4j.Slf4j;
import org.springblade.common.cache.CacheNames;
import org.springblade.core.constant.AppConstant;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.utils.WebUtil;
import org.springblade.core.tool.exception.ServiceException;
import org.springblade.core.tool.support.Kv;
import org.springblade.core.tool.utils.Func;
import org.springblade.modules.auth.enums.UserEnum;
import org.springblade.modules.auth.granter.CaptchaTokenGranter;
import org.springblade.modules.auth.provider.ITokenGranter;
import org.springblade.modules.auth.provider.TokenGranterBuilder;
import org.springblade.modules.auth.provider.TokenParameter;
import org.springblade.modules.auth.service.BladeMicroAppTokenService;
import org.springblade.modules.auth.utils.TokenUtil;
import org.springblade.modules.system.entity.Tenant;
import org.springblade.modules.system.entity.ThirdBindCountRecord;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.entity.UserInfo;
import org.springblade.modules.system.service.ITenantService;
import org.springblade.modules.system.service.IThirdBindCountRecordService;
import org.springblade.modules.system.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping(AppConstant.APPLICATION_AUTH_NAME+"/micro-app/phone")
@Api(value = "微信小程序手机号授权认证", tags = "微信小程序手机号授权接口")
@Slf4j
public class BladeMicroAppPhoneEndPoint {

    @Autowired
    private ITenantService tenantService;

    @Autowired
    private BladeRedis bladeRedis;

    @Autowired
    private IUserService userService;

    @Autowired
    private IThirdBindCountRecordService thirdBindCountRecordService;

    @PostMapping("/login")
    @ApiOperation(value = "微信小程序手机号登录", notes = "传入code,加密encryptedData和iv,短信验证码msg,短信验证码KEY:header['Phone-Msg-Key']")
    public Kv login(@ApiParam(value = "tell", required = true) @RequestParam String tell,
                    @ApiParam(value = "msg", required = true) @RequestParam String msg){

        Kv authInfo = Kv.create();
        String key = WebUtil.getRequest().getHeader(TokenUtil.PHONE_SMS_KEY);
        // 获取缓存的短信验证码
        String sms = bladeRedis.get(CacheNames.SMS_CODE_KEY + key);
        if (StrUtil.isEmpty(sms)){
            throw new ServiceException("验证码过期,请重新发送");
        }
        if (!sms.equals(msg)){
            throw new ServiceException(TokenUtil.CAPTCHA_NOT_CORRECT);
        }
        List<User> users = userService.list(new LambdaQueryWrapper<User>()
                .eq(User::getPhone, tell)
                .eq(User::getIsDeleted, 0)
                .orderByAsc(User::getCreateTime));

        if (CollectionUtil.isEmpty(users)) {
            return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_msg", "用户不存在");
        }

        UserInfo userInfo = grant(users.get(0));

        if (userInfo == null || userInfo.getUser() == null) {
            return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_msg", "用户名或密码不正确");
        }

        if (Func.isEmpty(userInfo.getRoles())) {
            return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_msg", "未获得用户的角色信息");
        }

        return TokenUtil.createAuthInfo(userInfo);
    }

    @PostMapping("/bind")
    @ApiOperation(value = "绑定租户电话，并获取令牌", notes = "传入OPENID,账号:account,密码:password|验证码KEY:header['Captcha-Key'],验证码:header['Captcha-Code']")
    public Kv bindphone(@ApiParam(value = "电话", required = true) @RequestParam String tell,
                        @ApiParam(value = "账号", required = true) @RequestParam(required = true) String username,
                        @ApiParam(value = "密码", required = true) @RequestParam(required = true) String password){

        Kv authInfo = Kv.create();

        TokenParameter tokenParameter = new TokenParameter();
        tokenParameter.getArgs().set("tenantId", "000000").set("username", username).set("password", password)
                .set("grantType", CaptchaTokenGranter.GRANT_TYPE).set("userType", UserEnum.APP.getName());

        ITokenGranter granter = TokenGranterBuilder.getGranter(CaptchaTokenGranter.GRANT_TYPE);
        UserInfo userInfo = null;
        try {
            userInfo = granter.grant(tokenParameter);
        } catch (ServiceException e) {
            return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", e.getMessage());
        }
        if (userInfo == null || userInfo.getUser() == null) {
            return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "用户名或密码不正确");
        }
        long count = userService.count(Wrappers.<User>lambdaQuery()
                .eq(User::getPhone,tell));
        if (count > 0){
            throw new ServiceException("电话号已经绑定不可重复绑定...");
        }
        User user = userInfo.getUser();
        if (StrUtil.isNotEmpty(user.getPhone())){
            return authInfo.set("error_code", HttpServletResponse.SC_BAD_REQUEST).set("error_description", "用户手机号已存在");
        }
        user.setPhone(tell);
        userService.updateById(user);

        return TokenUtil.createAuthInfo(userInfo);
    }

    public UserInfo grant(User user) {
        String tenantId = user.getTenantId();
        String username = user.getAccount();
        String password = user.getPassword();
        UserInfo userInfo = null;
        if (StrUtil.isNotBlank(username) && StrUtil.isNotBlank(password)) {
            // 获取租户信息
            Tenant tenant = tenantService.getByTenantId(tenantId);
            if (TokenUtil.judgeTenant(tenant)) {
                throw new ServiceException(TokenUtil.USER_HAS_NO_TENANT_PERMISSION);
            }
            // 根据不同用户类型调用对应的接口返回数据，用户可自行拓展
//            userInfo = userService.userInfo(tenantId, username, password, UserEnum.WEB);

            // 根据不同用户类型调用对应的接口返回数据，用户可自行拓展
            // 获取用户类型
            String userType = Func.toStr(WebUtil.getRequest().getHeader(TokenUtil.USER_TYPE_HEADER_KEY), TokenUtil.DEFAULT_USER_TYPE);
            if (userType.equals(UserEnum.WEB.getName())) {
                userInfo = userService.userInfo(tenantId, username, password, UserEnum.WEB);
            } else if (userType.equals(UserEnum.APP.getName())) {
                userInfo = userService.userInfo(tenantId, username, password, UserEnum.APP);
            } else {
                userInfo = userService.userInfo(tenantId, username, password, UserEnum.OTHER);
            }
        }
        return userInfo;
    }
}
