package com.fs.web.controller.system;

import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSONObject;
import com.fs.common.core.domain.R;
import com.fs.common.core.domain.entity.SysRole;
import com.fs.common.core.domain.model.LoginUser;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.exception.ServiceException;
import com.fs.common.utils.PatternUtils;
import com.fs.common.utils.ServletUtils;
import com.fs.common.utils.ip.IpUtils;
import com.fs.framework.web.service.TokenService;
import com.fs.his.utils.ConfigUtil;
import com.fs.hisStore.config.MedicalMallConfig;
import com.fs.system.service.ISysRoleService;
import com.fs.system.service.ISysUserService;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.*;
import com.fs.common.constant.Constants;
import com.fs.common.core.domain.AjaxResult;
import com.fs.common.core.domain.entity.SysMenu;
import com.fs.common.core.domain.entity.SysUser;
import com.fs.common.core.domain.model.LoginBody;
import com.fs.common.utils.SecurityUtils;
import com.fs.framework.web.service.SysLoginService;
import com.fs.framework.web.service.SysPermissionService;
import com.fs.system.service.ISysMenuService;

/**
 * 登录验证
 *

 */
@RestController
@Slf4j
public class SysLoginController
{
    @Autowired
    private SysLoginService loginService;

    @Autowired
    private ISysMenuService menuService;

    @Autowired
    private SysPermissionService permissionService;

    @Autowired
    private ISysRoleService roleService;

    @Autowired
    private ConfigUtil configUtil;

    @Autowired
    private MedicalMallConfig medicalMallConfig;

    @Autowired
    RedisCache redisCache;

    @Autowired
    private ISysUserService userService;

    @Autowired
    private TokenService tokenService;

    @Autowired
    private UserDetailsService userDetailsService;

    /**
     * 登录方法
     *
     * @param loginBody 登录信息
     * @return 结果
     */
    @PostMapping("/login")
    public AjaxResult login(@RequestBody LoginBody loginBody)
    {
        if (!PatternUtils.checkPassword(loginBody.getPassword())) {
            return AjaxResult.error("密码格式不正确,需包含字母、数字和特殊字符,长度为 8-20 位");
        }
        AjaxResult ajax = AjaxResult.success();
        // 生成令牌
        String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
                loginBody.getUuid());
        ajax.put(Constants.TOKEN, token);
        return ajax;
    }

    /**
     * 获取用户信息
     *
     * @return 用户信息
     */
    @GetMapping("getInfo")
    public AjaxResult getInfo()
    {
        SysUser user = SecurityUtils.getLoginUser().getUser();
        // 角色集合
        Set<String> roles = permissionService.getRolePermission(user);
        // 权限集合
        Set<String> permissions = permissionService.getMenuPermission(user);
        //药品商城参数
        AjaxResult ajax = AjaxResult.success();

        if(medicalMallConfig!=null){
            ajax.put("medicalMallConfig", medicalMallConfig);
        }
        ajax.put("user", user);
        SysRole isAdmin = new SysRole();
        getIsAdmin(isAdmin, permissions, user);
        ajax.put("isAdmin", isAdmin);
        ajax.put("roles", roles);
        ajax.put("permissions", permissions);

        return ajax;
    }

    /**
     * 获取电话地址权限
     * @param isAdmin
     * @param permissions
     * @param user
     */
    private void getIsAdmin(SysRole isAdmin, Set<String> permissions, SysUser user) {
        isAdmin.setIsCheckAddress(0);
        isAdmin.setIsCheckPhone(0);
        if (permissions.contains("*:*:*")){
            isAdmin.setIsCheckAddress(1);
            isAdmin.setIsCheckPhone(1);
        }else {
            List<SysRole> roleList = user.getRoles();
            if (roleList != null && !roleList.isEmpty()) {
                Long[] roleIds = roleList.stream().map(SysRole::getRoleId).toArray(Long[]::new);
//                isAdmin = roleService.getIsCheckPhone(roleIds)?1:0;
                SysRole isCheckPermission = roleService.getIsCheckPermission(roleIds);
                if (isCheckPermission != null) {
                    isAdmin.setIsCheckPhone(isCheckPermission.getIsCheckPhone());
                    isAdmin.setIsCheckAddress(isCheckPermission.getIsCheckAddress());
                }
            }
        }
    }

    /**
     * 获取路由信息
     *
     * @return 路由信息
     */
    @GetMapping("getRouters")
    public AjaxResult getRouters()
    {
        Long userId = SecurityUtils.getUserId();
        List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
        return AjaxResult.success(menuService.buildMenus(menus));
    }

    @PostMapping("/checkIsNeedCheck")
    public boolean checkIsNeedCheck(@RequestBody LoginBody loginBody)
    {
//        return  false;
        return loginService.checkIsNeedCheck(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(), loginBody.getUuid());
    }

    @PostMapping("/checkCode")
    public AjaxResult checkCode(@RequestBody Map<String,String> map)
    {
        String phone = map.get("phone");
        String code = map.get("code");
        String smsKey = "doctorLogin:sms:" + map.get("phone");
        String smsCode = redisCache.getCacheObject(smsKey);

        if (smsCode == null) {
            throw new ServiceException("验证码已过期，请重新发送");
        } else {
            String string = redisCache.getCacheObject("doctorLogin:sms:" + phone).toString();
            if (!string.equals(code)){
                throw new ServiceException("验证码错误");
            }else{
                redisCache.deleteObject("doctorLogin:sms:" + phone);
                List<SysUser> sysUsers = userService.selectUserByPhone(phone);
                if(sysUsers.size()>1){
                    throw new ServiceException("此电话号码绑定了多个医生，请核实");
                }
                SysUser sysUser = sysUsers.get(0);
                String ipAddr = IpUtils.getIpAddr(ServletUtils.getRequest());
                String username = sysUser.getUserName();

                // 调 UserDetailsServiceImpl.loadUserByUsername 获取完整 LoginUser
                sysUser.setLoginIp(ipAddr);
                sysUser.setLoginDate(new Date());
                userService.updateUserProfile(sysUser);
                LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(username);
                String token = tokenService.createToken(loginUser);
                AjaxResult ajax = AjaxResult.success();
                ajax.put(Constants.TOKEN, token);
                return ajax;
            }
        }
    }

    @GetMapping("/checkWechatScan")
    public AjaxResult checkWechatScan(@RequestParam String ticket)
    {
        String status = redisCache.getCacheObject("wechat:scan:" + ticket);
        if ("ok".equals(status)) {
            String username = redisCache.getCacheObject("login:ticket:" + ticket);
            redisCache.deleteObject("login:ticket:" + ticket);
            redisCache.deleteObject("wechat:scan:" + ticket);
            SysUser sysUser = userService.selectUserByUserName(username);

            String ipAddr = IpUtils.getIpAddr(ServletUtils.getRequest());
            String loginIp = sysUser.getLoginIp();
            if (com.fs.common.utils.StringUtils.isEmpty(loginIp)) {
                sysUser.setLoginIp(ipAddr.trim());
            } else {
                List<String> ipList = Arrays.stream(loginIp.split(","))
                        .map(String::trim)       // 去掉前后空格
                        .filter(s -> !s.isEmpty())
                        .distinct()              // 去重
                        .collect(Collectors.toList());

                String newIp = ipAddr.trim();
                if (!ipList.contains(newIp)) {
                    ipList.add(newIp);
                }

                sysUser.setLoginIp(String.join(",", ipList));
            }

            sysUser.setLoginDate(new Date());
            userService.updateUserProfile(sysUser);
            LoginUser loginUser = (LoginUser) userDetailsService.loadUserByUsername(username);
            String token = tokenService.createToken(loginUser);
            if (token != null){
                return AjaxResult.success(Constants.TOKEN, token);
            }
            return AjaxResult.success("waiting");
        }else if (com.fs.common.utils.StringUtils.isNotEmpty(status)&&status.startsWith("error:")) {
            // 把错误返回给前端
            throw new ServiceException(status);
        }
        return null;
    }

    @PostMapping("/getWechatQrCode")
    public AjaxResult getWechatQrCode(@RequestBody Map<String,String> params) throws Exception {
        Map<String,String> qr = loginService.getWechatQrCode(params.get("username"));
        return AjaxResult.success(qr);
    }
    @GetMapping("/callback")
    public String wechatCallback(@RequestParam String code, @RequestParam String state) {
        try {
            log.info("触发回调");
            loginService.handleCallback(code, state);
            return "success"; // 微信要求返回内容，显示给用户即可
        } catch (Exception e) {
            return "error";
        }
    }
}
