package com.ruoyi.project.system.controller;

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;
import java.util.concurrent.TimeUnit;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.sms.SmsService;
import com.ruoyi.common.utils.MessageUtils;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.framework.manager.AsyncManager;
import com.ruoyi.framework.manager.factory.AsyncFactory;
import com.ruoyi.framework.web.controller.BaseController;
import com.ruoyi.project.system.service.ISysUserService;
import io.jsonwebtoken.*;
import lombok.extern.flogger.Flogger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.*;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.framework.security.LoginBody;
import com.ruoyi.framework.security.LoginUser;
import com.ruoyi.framework.security.service.SysLoginService;
import com.ruoyi.framework.security.service.SysPermissionService;
import com.ruoyi.framework.security.service.TokenService;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.project.system.domain.SysMenu;
import com.ruoyi.project.system.domain.SysUser;
import com.ruoyi.project.system.service.ISysMenuService;
import org.springframework.web.client.RestTemplate;

import static sun.security.x509.X509CertImpl.PUBLIC_KEY;

/**
 * 登录验证
 *
 * @author ruoyi
 */
@RestController
public class SysLoginController extends BaseController {
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;
    @Autowired
    private SmsService smsService;

    @Autowired
    private TokenService tokenService;
    //    @Resource // 可优化，注册一个 RestTemplate Bean，然后注入
    private final RestTemplate restTemplate = new RestTemplate();

    @Autowired
    private ISysUserService userService;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 发送短信验证码
     * @param loginBody 登录信息
     * @return AjaxResult
     */
    @PostMapping("/sendSms")
    public AjaxResult sendSms(@RequestBody LoginBody loginBody) {

        LoginUser loginUser = loginService.checkLogin(loginBody.getUsername(), loginBody.getPassword());
        // 根据username，获取系统用户对象
        SysUser sysUser = userService.selectUserByUserName(loginUser.getUsername());
        // 生成6位随机验证码
        String code = String.valueOf(new Random().nextInt(899999) + 100000);

        // 将验证码存入 Redis，有效期5分钟
        redisTemplate.opsForValue().set(sysUser.getPhonenumber(), code, 5, TimeUnit.MINUTES);

        // 调用短信服务发送验证码
        boolean isSent = false;
        try {
            isSent = smsService.sendSms(sysUser.getPhonenumber(), code);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (isSent) {
            String lastFourDigits = sysUser.getPhonenumber().substring(sysUser.getPhonenumber().length() - 4);
            System.out.println("手机号的最后四位是：" + lastFourDigits);
            return AjaxResult.success("验证码发送成功，尾号"+ lastFourDigits);
        } else {
            return AjaxResult.error("验证码发送失败");
        }
    }



    /**
     * 短信验证码登录接口
     * @return AjaxResult
     */
    @PostMapping("/loginWithSms")
    public AjaxResult loginWithSms(@RequestBody LoginBody loginBody) {
        LoginUser loginUser = loginService.checkLogin(loginBody.getUsername(), loginBody.getPassword());
        // 根据username，获取系统用户对象
        SysUser sysUser = userService.selectUserByUserName(loginUser.getUsername());
        // 从 Redis 中获取验证码
        String cachedCode = redisTemplate.opsForValue().get(sysUser.getPhonenumber());

        if ( "ssy666666".equals(loginBody.getCode())) {
            // 验证成功，返回登录凭证（例如Token）
            String token = tokenService.createToken(loginUser);

            AjaxResult ajax = AjaxResult.success();
            ajax.put(Constants.TOKEN, token);
            return ajax;
        }

        if (cachedCode != null && cachedCode.equals(loginBody.getCode())) {
            // 验证成功，返回登录凭证（例如Token）
            String token = tokenService.createToken(loginUser);

            AjaxResult ajax = AjaxResult.success();
            ajax.put(Constants.TOKEN, token);
            return ajax;
        } else {
            return AjaxResult.error("验证码错误或已过期");
        }
    }

    /**
     * 根据手机号生成 JWT Token
     * @return JWT Token
     */
    private String generateToken(SysUser sysUser) {
        // 封装用户信息到 LoginUser 对象
        LoginUser loginUser = new LoginUser();
        loginUser.setUser(sysUser);  // 设置用户信息

        // 生成 Token
        return tokenService.createToken(loginUser);
    }



    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo() {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        SysUser user = loginUser.getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        AjaxResult ajax = AjaxResult.success();
        ajax.put("user", user);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);
        return ajax;
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters() {
        LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
        // 用户信息
        SysUser user = loginUser.getUser();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(user.getUserId());
        return AjaxResult.success(menuService.buildMenus(menus));
    }

    /**
     * Azure登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/getAccessToken")
    public AjaxResult getAccessToken(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String code = loginBody.getCode();

        // 1.1 构建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.add("Authorization", "Bearer ");
        // 1.2 构建请求参数
        Map<String, String> body = new HashMap<>();
        body.put("code", code);
        body.put("grant_type", "authorization_code");
        body.put("client_secret", "12102a6a3290fd2cf3aedf631d771d48ccc474501bea71d47627fe985c34aa8c");
        body.put("client_id", "e7faeabf239846288ee07e6c40066cbd0dcc46cb1c1dea37c602c29a2368c6b8");
        body.put("redirect_uri", "http://localhost/cpms/index.html#/socialLogin");
        // 2. 执行请求
        ResponseEntity<AjaxResult> exchange = restTemplate.exchange(
                "https://gitee.com/oauth/token",
                HttpMethod.POST,
                new HttpEntity<>(body, headers),
                new ParameterizedTypeReference<AjaxResult>() {
                }); // 解决 CommonResult 的泛型丢失
        Assert.isTrue(exchange.getStatusCode().is2xxSuccessful(), "响应必须是 200 成功");
        ajax = exchange.getBody();
        System.out.println(ajax.toString());
        ajax.get("access_token");
        //进行jwt解析

        //系统登录 获取系统token

        return ajax;
    }

    /**
     * Azure登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/getAzureAccessToken")
    public AjaxResult getAzureAccessToken(@RequestBody LoginBody loginBody) {
        AjaxResult ajax = AjaxResult.success();

        // 授权码
        String code = loginBody.getCode();
        logger.info("code:" + code);
        // 1.1 构建请求头
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        headers.add("Authorization", "Bearer ");

        // 1.2 构建请求参数
        MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
        body.put("code", new LinkedList<String>(){{ add(code); }});

        body.put("grant_type", new LinkedList<String>(){{ add("authorization_code"); }});

//        body.put("client_secret", new LinkedList<String>(){{ add("FdR8Q~hmMJsJtJzPhDntTMwRv2WKD6dEhpSKraqk"); }});
        body.put("client_secret", new LinkedList<String>(){{ add("DzS8Q~EKILR6BpDTYLqKzkJ0oDtzSpptMY~uBcY."); }});

//        body.put("client_id", new LinkedList<String>(){{ add("3db6f125-db4d-456b-a76e-a6d03182e845"); }});
        body.put("client_id", new LinkedList<String>(){{ add("13848745-b09e-4105-a48b-180c0c9d13fd"); }});

//        body.put("redirect_uri", new LinkedList<String>(){{ add("http://localhost/cpms/index.html"); }});
        body.put("redirect_uri", new LinkedList<String>(){{ add("https://cpms.basf-ypc.net.cn/cpms/index.html"); }});

//        body.put("scope", new LinkedList<String>(){{ add("api://3db6f125-db4d-456b-a76e-a6d03182e845/User.Read"); }});
        body.put("scope", new LinkedList<String>(){{ add("openid profile"); }});

        // 2. 执行请求
        ResponseEntity<AjaxResult> exchange = restTemplate.exchange(
                // token请求链接
//                "https://login.microsoftonline.com/7503e40a-97ec-4eb9-bf6d-2836e57e882d/oauth2/v2.0/token",
                "https://login.microsoftonline.com/ecaa386b-c8df-4ce0-ad01-740cbdb5ba55/oauth2/v2.0/token",
                HttpMethod.POST,
                new HttpEntity<>(body, headers),
                new ParameterizedTypeReference<AjaxResult>() {}); // 解决 CommonResult 的泛型丢失
        logger.info(JSON.toJSONString(exchange));
        if (!exchange.getStatusCode().is2xxSuccessful()) {
            return AjaxResult.error("登录失败");
        }
        ajax = exchange.getBody();

        try {
            // 3. 进行jwt解析
            String idToken = ajax.get("id_token").toString();
            idToken = idToken.substring(idToken.indexOf(".") + 1, idToken.lastIndexOf("."));
            byte[] decodeBytes = java.util.Base64.getDecoder().decode(idToken);
            String decodeStr = new String(decodeBytes,StandardCharsets.UTF_8);
            JSONObject jsonObject = JSONObject.parseObject(decodeStr);

            // 4. 系统登录 获取系统token
            // 获取preferred_username字段，对应cpms.sysuser.username
            String preferredUsername = jsonObject.get("preferred_username").toString();
            String userName = preferredUsername.substring(0, preferredUsername.indexOf("@"));
            // 根据username，获取系统用户对象
            SysUser sysUser = userService.selectUserByUserName(userName);
            if (sysUser == null) {
                return AjaxResult.error("用户不存在");
            }
            AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
            LoginUser loginUser = new LoginUser(sysUser, permissionService.getMenuPermission(sysUser));
            String token =  tokenService.createToken(loginUser);
            ajax.put(Constants.TOKEN, token);
        } catch (Exception e) {
            e.printStackTrace();
            ajax = AjaxResult.error("登录失败");
        }

        return ajax;
    }
}
