package com.bonus.auth.controller;

import com.alibaba.fastjson.JSONObject;
import com.bonus.auth.config.LoginType;
import com.bonus.auth.factory.LoginStrategyFactory;
import com.bonus.auth.form.LoginBody;
import com.bonus.auth.form.LoginIsAdminBody;
import com.bonus.auth.form.RegisterBody;
import com.bonus.auth.service.*;
import com.bonus.common.core.constant.CacheConstants;
import com.bonus.common.core.constant.SecurityConstants;
import com.bonus.common.core.domain.R;
import com.bonus.common.core.exception.ServiceException;
import com.bonus.common.core.utils.JwtUtils;
import com.bonus.common.core.utils.StringUtils;
import com.bonus.common.core.utils.encryption.Sm4Utils;
import com.bonus.common.core.web.domain.AjaxResult;
import com.bonus.common.redis.service.RedisService;
import com.bonus.common.security.auth.AuthUtil;
import com.bonus.common.security.service.TokenService;
import com.bonus.common.security.utils.SecurityUtils;
import com.bonus.config.SystemConfig;
import com.bonus.system.api.RemoteConfigService;
import com.bonus.system.api.RemoteLogService;
import com.bonus.system.api.RemoteUserService;
import com.bonus.system.api.domain.SysUser;
import com.bonus.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Token 控制器
 * 处理登录、获取验证码、登出、刷新令牌和注册功能
 */
@RestController
@Slf4j
public class TokenController {

   @Resource
   private SystemConfig config;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private SysLoginService sysLoginService;

    @Autowired
    private LoginStrategyFactory loginStrategyFactory;

    @Resource
    private RemoteUserService remoteUserService;

    @Autowired
    private SysPasswordService passwordService;

    @Autowired
    private PasswordValidatorService passwordValidatorService;

    @Autowired
    private SysRecordLogService logService;

    @Autowired
    private RedisService redisService;

    @Resource
    private RemoteConfigService configService;

    @Value("${third-party-login.iws.webAppId}")
    private String iwsWebAppId;

    @Value("${third-party-login.iws.webUrl}")
    private String iwsWebUrl;

    @Value("${third-party-login.iws.h5AppId}")
    private String iwsH5AppId;

    @Value("${third-party-login.iws.h5Url}")
    private String iwsH5Url;

    @PostMapping("isAdmin")
    public R<?> isAdmin(@RequestBody LoginIsAdminBody form) {
        if (!config.isAdmin()) {
            return R.ok(false);
        }
        String password = Sm4Utils.decrypt(form.getPassword());
        passwordValidatorService.validateLoginParameters(form.getUsername(), password);
        //通过用户名获取人员信息
        R<LoginUser> userResult = remoteUserService.getUserInfo(form.getUsername(), SecurityConstants.INNER);
        // 验证用户查询结果
        passwordValidatorService.validateUserResult(form.getUsername(), userResult);
        LoginUser userInfo = userResult.getData();
        SysUser user = userInfo.getSysUser();
        passwordValidatorService.validateApprovalStatus(form.getUsername(), user);
        // 验证用户状态
        passwordValidatorService.validateUserStatus(form.getUsername(), user);
        // 验证密码
        passwordService.validate(user, password, System.currentTimeMillis());
        // 处理IP校验
        passwordValidatorService.handleIpValidation(form.getUsername(), user);
        if (userResult.getData() == null || R.FAIL == userResult.getCode()) {
            return R.fail("登录用户不存在");
        }
        Set<String> roles = userResult.getData().getRoles();
        return R.ok(roles.contains("admin"));
    }

    @PostMapping("isLogin")
    public R<?> isLogin(@RequestBody LoginBody form) {
        LoginStrategy strategy = loginStrategyFactory.getStrategy(form.getLoginType());
        if (strategy == null) {
            return R.fail("不支持的登录方式");
        }
        if (form.getLoginType()== LoginType.EMAIL_OTP || form.getLoginType()== LoginType.PHONE_OTP ){
            form.setPassword(form.getVerificationCode());
        }
        LoginUser login = strategy.login(form.getUsername(), form.getPassword());
        return R.ok(tokenService.isLogin(String.valueOf(login.getSysUser().getUserId())));
    }

    @PostMapping("login")
    public R<?> login(@RequestBody LoginBody form) {
        // 获取相应的登录策略
        LoginStrategy strategy = loginStrategyFactory.getStrategy(form.getLoginType());
        if (strategy == null) {
            return R.fail("不支持的登录方式");
        }
        if (form.getLoginType()== LoginType.EMAIL_OTP || form.getLoginType()== LoginType.PHONE_OTP ){
            form.setPassword(form.getVerificationCode());
        }

        /**对系统并发数进行判断*/
        long concurrency = 100;
        AjaxResult result = configService.getConfigKey("sys.backend.concurrency");
        if (result.isSuccess())
        {
            concurrency = Long.parseLong(result.get("msg").toString());
        }
        Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
        if (keys.size() >= concurrency){
            return R.fail("当前系统用户并发数超过系统配置，请稍后再试");
        }

        String username = Sm4Utils.decrypt(form.getUsername());
        String password = Sm4Utils.decrypt(form.getPassword());

        LoginUser login = strategy.login(username, password);
        logService.saveLogin(username, "登录", "登录成功", null, "成功");
        if (LoginType.KITCHEN_PHONE_PASSWORD.equals(form.getLoginType())) {
            return R.ok(tokenService.createKitchenStaffToken(login));
        } else {
            return R.ok(tokenService.createToken(login));
        }

    }

    /**
     * i皖送登录
     * @return
     */
    @PostMapping("iwsLogin")
    public R<?> iwsLogin(@RequestBody LoginBody form) {
        //获取i皖送传过来的票据
        String ticket = form.getTicket();
        log.info("ticket=" + ticket);
        if (StringUtils.isNotEmpty(ticket)) {
            LoginUser loginUser = new LoginUser();
            if (form.getSysType()!=null && "1".equals(form.getSysType())){
                log.info("app端登录");
                //loginUser = sysLoginService.iwsH5Login(ticket,iwsH5AppId,iwsH5Url);
                //h5和web端调用同一个接口
                loginUser = sysLoginService.iwsWebLogin(ticket,iwsH5AppId,iwsWebUrl);
            } else if (form.getSysType()!=null && "0".equals(form.getSysType())) {
                loginUser = sysLoginService.iwsWebLogin(ticket,iwsWebAppId,iwsWebUrl);
            }else {
                throw new ServiceException("登录失败，请稍后重试");
            }
            logService.saveLogin(loginUser.getSysUser().getUserName(), "登录", "登录成功", null, "成功");
            //生成系统token
            return R.ok(tokenService.createToken(loginUser));

        }
        return R.fail("登录失败！");
    }

    /**
     * 获取手机验证码
     *
     * @param form 登录表单
     * @return 验证码发送结果
     */
    @PostMapping("getPhoneCode")
    public R<?> getPhoneCode(@RequestBody LoginBody form) {
        return sysLoginService.getPhoneCode(form.getUsername(), form.getVerificationCodeType());
    }

    /**
     * 用户登出
     *
     * @param request HTTP 请求
     * @return 登出结果
     */
    @PostMapping("logout")
    public R<?> logout(HttpServletRequest request) {
        try {
            String token = SecurityUtils.getToken(request);
            if (StringUtils.isNotEmpty(token)) {
                String key = JwtUtils.getUserKey(token);
                boolean key1 = tokenService.isKey(key);
                if (key1) {
                    String username = JwtUtils.getUserName(token);
                    String userId = JwtUtils.getUserId(token);
                    AuthUtil.logoutByToken(token);
                    tokenService.delExistingToken(Long.valueOf(userId));
                    sysLoginService.logout(username, userId);
                    logService.saveLogout(username, "退出登录", "退出成功", userId, "成功");
                }
                return R.ok();
            }
        } catch (Exception e) {
            log.error("登出失败: {}", e.getMessage(), e);
        }
        sysLoginService.logout("", "");
        return R.ok();
    }

    /**
     * 刷新令牌
     *
     * @param request HTTP 请求
     * @return 刷新结果
     */
    @PostMapping("refresh")
    public R<?> refresh(HttpServletRequest request) {
        try {
            LoginUser loginUser = tokenService.getLoginUser(request);
            if (StringUtils.isNotNull(loginUser)) {
                tokenService.refreshToken(loginUser);
                return R.ok();
            }
        } catch (Exception e) {
            log.error("刷新令牌失败: {}", e.getMessage(), e);
        }
        return R.fail("刷新令牌失败");
    }

    /**
     * 用户注册
     *
     * @param registerBody 注册表单
     * @return 注册结果
     */
    @PostMapping("register")
    public R<?> register(@RequestBody RegisterBody registerBody) {
        sysLoginService.register(registerBody);
        logService.saveRegister(registerBody.getUsername(), "注册", "注册成功", null, "成功");
        return R.ok();
    }
}
