package com.yonge.cooleshow.auth.core.provider;

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

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.InternalAuthenticationServiceException;
import org.springframework.security.authentication.LockedException;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.transaction.annotation.Transactional;

import com.yonge.cooleshow.auth.api.dto.SysUserInfo;
import com.yonge.cooleshow.auth.api.entity.LoginEntity;
import com.yonge.cooleshow.auth.api.entity.SysUser;
import com.yonge.cooleshow.auth.config.token.PhoneAuthenticationToken;
import com.yonge.cooleshow.auth.service.SysUserDeviceService;
import com.yonge.cooleshow.auth.service.SysUserService;
import com.yonge.cooleshow.common.service.IdGeneratorService;

public class PhoneAuthenticationProvider extends AbstractAuthenticationProvider {

    private UserDetailsService userDetailsService;

    private IdGeneratorService smsCodeService;

    private SysUserService sysUserService;

    private SysUserDeviceService sysUserDeviceService;

    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, Authentication authentication) throws AuthenticationException {
        if (authentication.getCredentials() == null) {
            throw new BadCredentialsException(this.messages.getMessage("PhoneAuthenticationProvider.badCredentials", "Bad credentials"));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    protected UserDetails retrieveUser(String username, Authentication authentication) throws AuthenticationException {
        LoginEntity loginEntity = (LoginEntity) authentication.getCredentials();
        if (loginEntity == null) {
            throw new BadCredentialsException("Bad credentials");
        }

        String smsCode = loginEntity.getSmsCode();
        String phone = loginEntity.getPhone();
        String qrCode = loginEntity.getQrCode();
        if (StringUtils.isNotEmpty(qrCode) && StringUtils.isEmpty(smsCode)) {
            // 二维码验证
            boolean b = sysUserService.verifyQrCode(phone, qrCode);
            if (!b) {
                throw new BadCredentialsException("二维码校验失败");
            }
        } else {
            // 验证码验证
            boolean b = smsCodeService.verifyValidCode(phone, smsCode, "SMS_VERIFY_CODE_LOGIN");
            if (!b) {
                throw new BadCredentialsException("验证码校验失败");
            }
        }

        String clientId = loginEntity.getClientId();
        Boolean isRegister = loginEntity.getIsSurportRegister();
        String loginUserType = loginEntity.getLoginUserType();
        String deviceNum = loginEntity.getDeviceNum();

        SysUserInfo userInfo = sysUserService.queryUserInfoByPhone(phone);

        if (userInfo == null) {
            if (isRegister == false || StringUtils.equals("SYSTEM", clientId)) {
                throw new LockedException("用户不存在");
            }

            userInfo = sysUserService.registerUser(loginEntity.getPhone(), clientId, loginUserType);

            if (Objects.nonNull(userInfo.getSysUser())) {
                // 自动添加系统默认IM帐号为好友，并自动发送通知消息
                sysUserService.sendSysCustomerServiceFriendMessage(userInfo.getSysUser());
            }

            if (StringUtils.isNotBlank(deviceNum)) {
                sysUserDeviceService.bindDevice(clientId, userInfo.getSysUser().getId(), deviceNum);
            }
        } else {
            SysUser user = userInfo.getSysUser();
            if (user == null) {
                throw new LockedException("用户不存在");
            }
            if (user.getLockFlag() == 1) {
                throw new LockedException("用户已锁定");
            }

            if (StringUtils.isNotBlank(deviceNum)) {
                sysUserDeviceService.bindDevice(clientId, user.getId(), deviceNum);
            }
            //登录
            if (userInfo.getSysUser().getUserType().contains(clientId)){
                return login(username);
            }
            //官网登录
            if(StringUtils.isNotEmpty(loginUserType) && userInfo.getSysUser().getUserType().contains(loginUserType)){
                return login(username);
            }

            /**********************************注册*********************************************/
            //不能注册的
            if(isRegister == false || StringUtils.equals("SYSTEM", clientId)){
                throw new LockedException("用户不存在");
            }

            user.setUpdateTime(new Date());
            if(StringUtils.isNotEmpty(loginUserType)){
                if (StringUtils.equalsIgnoreCase(loginUserType, "TEACHER")) {
                    user.setUserType(user.getUserType() + "," + loginUserType);
                    sysUserService.saveTeacher(user);
                } else if (StringUtils.equalsIgnoreCase(loginUserType, "STUDENT")) {
                    user.setUserType(user.getUserType() + "," + loginUserType);
                    sysUserService.saveStudent(user);
                }else {
                    throw new LockedException("用户不存在");
                }
            }else if(StringUtils.isNotEmpty(clientId)){
                if (StringUtils.equalsIgnoreCase(clientId, "TEACHER")) {
                    user.setUserType(user.getUserType() + "," + clientId);
                    sysUserService.saveTeacher(user);
                } else if (StringUtils.equalsIgnoreCase(clientId, "STUDENT")) {
                    user.setUserType(user.getUserType() + "," + clientId);
                    sysUserService.saveStudent(user);
                } else {
                    throw new LockedException("用户不存在");
                }
            }else{
                throw new LockedException("用户不存在");
            }
            sysUserService.update(user);
        }
        return login(username);
    }

    private UserDetails login(String username){
        UserDetails loadedUser;
        try {
            loadedUser = userDetailsService.loadUserByUsername(username);
        } catch (UsernameNotFoundException e) {
            throw e;
        } catch (Exception e) {
            throw new InternalAuthenticationServiceException(e.getMessage(), e);
        }

        if (loadedUser == null) {
            throw new InternalAuthenticationServiceException("账户不存在");
        } else {
            return loadedUser;
        }
    }

    @Override
    protected Authentication createSuccessAuthentication(Object principal, Authentication authentication, UserDetails user) {
        PhoneAuthenticationToken result = new PhoneAuthenticationToken(principal, authentication.getCredentials(), user.getAuthorities());
        result.setDetails(authentication.getDetails());
        return result;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return PhoneAuthenticationToken.class.isAssignableFrom(aClass);
    }

    public void setUserDetailsService(UserDetailsService userDetailsService) {
        this.userDetailsService = userDetailsService;
    }

    public void setSysUserService(SysUserService sysUserService) {
        this.sysUserService = sysUserService;
    }

    public void setSmsCodeService(IdGeneratorService smsCodeService) {
        this.smsCodeService = smsCodeService;
    }

    public void setSysUserDeviceService(SysUserDeviceService sysUserDeviceService) {
        this.sysUserDeviceService = sysUserDeviceService;
    }
}
