package com.ichangzuo.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ichangzuo.common.constant.RedisConstants;
import com.ichangzuo.common.constant.SystemConstants;
import com.ichangzuo.common.enums.ContactType;
import com.ichangzuo.common.exception.BusinessException;
import com.ichangzuo.common.result.Result;
import com.ichangzuo.config.property.AliyunSmsProperties;
import com.ichangzuo.core.security.service.PermissionService;
import com.ichangzuo.core.security.util.SecurityUtils;
import com.ichangzuo.module.mail.service.MailService;
import com.ichangzuo.module.sms.service.SmsService;
import com.ichangzuo.system.converter.UserConverter;
import com.ichangzuo.system.model.entity.*;
import com.ichangzuo.system.model.form.*;
import com.ichangzuo.common.base.BasePageQuery;
import com.ichangzuo.system.model.vo.TakeOrderPageVO;
import com.ichangzuo.system.model.vo.UserProfileVO;
import com.ichangzuo.system.mapper.UserMapper;
import com.ichangzuo.system.model.dto.UserAuthInfo;
import com.ichangzuo.system.model.bo.UserBO;
import com.ichangzuo.system.model.query.UserPageQuery;
import com.ichangzuo.system.model.query.DrawQuery;
import com.ichangzuo.system.model.dto.UserExportDTO;
import com.ichangzuo.system.model.vo.UserInfoVO;
import com.ichangzuo.system.model.vo.UserPageVO;
import com.ichangzuo.system.service.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

import static com.ichangzuo.common.constant.SystemConstants.*;
import static com.ichangzuo.common.result.ResultCode.*;

/**
 * 用户业务实现类
 *
 * @author haoxr
 * @since 2022/1/14
 */
@Service
@RequiredArgsConstructor
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    private final PasswordEncoder passwordEncoder;
    private final UserRoleService userRoleService;
    private final UserConverter userConverter;
    private final RoleMenuService roleMenuService;
    private final RoleService roleService;
    private final PermissionService permissionService;
    private final SmsService smsService;
    private final MailService mailService;
    private final AliyunSmsProperties aliyunSmsProperties;
    private final StringRedisTemplate redisTemplate;
    private final RealNameServiceImpl realNameService;
    private final AccountServiceImpl accountService;
    private final MessageServiceImpl messageService;
    private final IntegralServiceImpl integralService;
    private final OrderServiceImpl orderService;
    private final TakeOrderServiceImpl takeOrderService;
    private final UserBankServiceImpl userBankService;
    private final NewUserServiceImpl newUserService;
    private final StatisticsServiceImpl statisticsService;

    /**
     * 获取用户分页列表
     *
     * @param queryParams 查询参数
     * @return {@link IPage<UserPageVO>} 用户分页列表
     */
    @Override
    public IPage<UserPageVO> listPagedUsers(UserPageQuery queryParams) {

        // 参数构建
        int pageNum = queryParams.getPageNum();
        int pageSize = queryParams.getPageSize();
        Page<UserBO> page = new Page<>(pageNum, pageSize);
        // 查询数据
        Page<UserBO> userPage = this.baseMapper.listPagedUsers(page, queryParams);

        // 实体转换
        return userConverter.toPageVo(userPage);
    }

    /**
     * 获取用户表单数据
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public UserForm getUserFormData(Long userId) {
        return this.baseMapper.getUserFormData(userId);
    }

    /**
     * 新增用户
     *
     * @param userForm 用户表单对象
     * @return
     */
    @Override
    public boolean saveUser(UserForm userForm) {

        String username = userForm.getUsername();

        long count = this.count(new LambdaQueryWrapper<User>().eq(User::getUsername, username));
        Assert.isTrue(count == 0, "用户名已存在");

        // 实体转换 form->entity
        User entity = userConverter.toEntity(userForm);

        // 设置默认加密密码
        String defaultEncryptPwd = passwordEncoder.encode(SystemConstants.DEFAULT_PASSWORD);
        entity.setPassword(defaultEncryptPwd);

        // 新增用户
        boolean result = this.save(entity);

        if (result) {
            // 保存用户角色
            userRoleService.saveUserRoles(entity.getId(), userForm.getRoleIds());
        }
        return result;
    }

    /**
     * 更新用户
     *
     * @param userId   用户ID
     * @param userForm 用户表单对象
     * @return
     */
    @Override
    @Transactional
    public boolean updateUser(Long userId, UserForm userForm) {

        String username = userForm.getUsername();

        long count = this.count(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)
                .ne(User::getId, userId)
        );
        Assert.isTrue(count == 0, "用户名已存在");

        // form -> entity
        User entity = userConverter.toEntity(userForm);

        // 修改用户
        boolean result = this.updateById(entity);

        if (result) {
            // 保存用户角色
            userRoleService.saveUserRoles(entity.getId(), userForm.getRoleIds());
        }
        return result;
    }

    /**
     * 删除用户
     *
     * @param idsStr 用户ID，多个以英文逗号(,)分割
     * @return true|false
     */
    @Override
    public boolean deleteUsers(String idsStr) {
        Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的用户数据为空");
        // 逻辑删除
        List<Long> ids = Arrays.stream(idsStr.split(","))
                .map(Long::parseLong)
                .collect(Collectors.toList());
        return this.removeByIds(ids);

    }

    /**
     * 锁定/恢复用户
     *
     * @param idsStr 用户ID，多个以英文逗号(,)分割
     * @return true|false
     */
    @Override
    public boolean setUsersState(String idsStr, int state) {
        Assert.isTrue(StrUtil.isNotBlank(idsStr), "删除的用户数据为空");
        List<Long> ids = Arrays.stream(idsStr.split(","))
                .map(Long::parseLong)
                .toList();

        for(Long id: ids){
            User user = getById(id);
            user.setStatus(state);
            updateById(user);
        }

        return true;
    }

    /**
     * 根据用户名获取认证信息
     *
     * @param username 用户名
     * @return 用户认证信息 {@link UserAuthInfo}
     */
    @Override
    public UserAuthInfo getUserAuthInfo(String username) {
        UserAuthInfo userAuthInfo = this.baseMapper.getUserAuthInfo(username);
        if (userAuthInfo != null) {
            Set<String> roles = userAuthInfo.getRoles();
            if (CollectionUtil.isNotEmpty(roles)) {
                Set<String> perms = roleMenuService.getRolePermsByRoleCodes(roles);
                userAuthInfo.setPerms(perms);
            }

            // 获取最大范围的数据权限
            Integer dataScope = roleService.getMaximumDataScope(roles);
            userAuthInfo.setDataScope(dataScope);
        }
        return userAuthInfo;
    }


    /**
     * 获取导出用户列表
     *
     * @param queryParams 查询参数
     * @return {@link List< UserExportDTO >} 导出用户列表
     */
    @Override
    public List<UserExportDTO> listExportUsers(UserPageQuery queryParams) {
        return this.baseMapper.listExportUsers(queryParams);
    }

    /**
     * 获取登录用户信息
     *
     * @return {@link UserInfoVO}   用户信息
     */
    @Override
    public UserInfoVO getCurrentUserInfo() {

        String username = SecurityUtils.getUsername();

        // 获取登录用户基础信息
        User user = this.getOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)
                .select(
                        User::getId,
                        User::getUsername,
                        User::getNickname,
                        User::getAvatar
                )
        );
        // entity->VO
        UserInfoVO userInfoVO = userConverter.toUserInfoVo(user);

        // 用户角色集合
        Set<String> roles = SecurityUtils.getRoles();
        userInfoVO.setRoles(roles);

        // 用户权限集合
        if (CollectionUtil.isNotEmpty(roles)) {
            Set<String> perms = permissionService.getRolePermsFormCache(roles);
            userInfoVO.setPerms(perms);
        }
        return userInfoVO;
    }

    /**
     * 获取个人中心用户信息
     *
     * @param userId 用户ID
     * @return
     */
    @Override
    public UserProfileVO getUserProfile(Long userId) {
        UserBO entity = this.baseMapper.getUserProfile(userId);
        return userConverter.toProfileVO(entity);
    }

    /**
     * 修改个人中心用户信息
     *
     * @param formData 表单数据
     * @return
     */
    @Override
    public boolean updateUserProfile(UserProfileForm formData) {
        Long userId = SecurityUtils.getUserId();
        User entity = userConverter.toEntity(formData);
        entity.setId(userId);
        return this.updateById(entity);
    }


    /**
     * 修改用户密码
     *
     * @param userId 用户ID
     * @param data   密码修改表单数据
     * @return
     */
    @Override
    public boolean changePassword(Long userId, PasswordChangeForm data) {

        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }

        String oldPassword = data.getOldPassword();

        // 校验原密码
        if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
            throw new BusinessException("原密码错误");
        }
        // 新旧密码不能相同
        if (passwordEncoder.matches(data.getNewPassword(), user.getPassword())) {
            throw new BusinessException("新密码不能与原密码相同");
        }

//        String newPassword = data.getNewPassword();
        return resetPassword(userId, data.getNewPassword());
//                this.update(new LambdaUpdateWrapper<User>()
//                .eq(User::getId, userId)
//                .set(User::getPassword, passwordEncoder.encode(newPassword))
//        );
    }

    /**
     * 重置密码
     *
     * @param userId   用户ID
     * @param password 密码重置表单数据
     * @return
     */
    @Override
    public boolean resetPassword(Long userId, String password) {
        return this.update(new LambdaUpdateWrapper<User>()
                .eq(User::getId, userId)
                .set(User::getPassword, passwordEncoder.encode(password))
        );
    }

    @Override
    public Result<?> sendResetPasswordCode(String username, String contact) {
        User user = getOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)
                .select(
                        User::getId,
                        User::getStatus,
                        User::getEmail
                )
        );

        if(user==null){
            return Result.failed(USER_NOT_EXIST);
        }

        Integer state = user.getStatus();
        if(state==0){
            return Result.failed(USER_ACCOUNT_INVALID);
        }
        else if(state==1) {
            return Result.failed(USER_ACCOUNT_LOCKED);
        }

        ContactType type;
        if( contact.matches(REGREX_PHONE) ) {
            type = ContactType.MOBILE;
        }
        else if(contact.matches(REGREX_EMAIL)) {
            type = ContactType.EMAIL;
        }
        else
            return Result.failed(PARAM_ERROR);

        if(type==ContactType.EMAIL){
            if(state!=2){
                return Result.failed(USER_EMAIL_UNBIND);
            }

            if(!contact.equals(user.getEmail())){
                return Result.failed(USER_EMAIL_INVALID);
            }
        }
        else{
            Account account = getAccountById(user.getId());

            if(account.getIsPhone()!=1){
                return Result.failed(USER_PHONE_UNBIND);
            }

            if(!contact.equals(account.getPhone())){
                return Result.failed(USER_PHONE_INVALID);
            }
        }

        if( sendVerificationCode(contact, "重置密码", type) ){
            return Result.success(user.getId());
        }
        else {
            return Result.failed(MESSAGE_SERVICE_ERROR);
        }
    }

    @Override
    public boolean sendVerificationCode(String contact, String subject){
        ContactType type;
        if( contact.matches(REGREX_PHONE) ) {
            type = ContactType.MOBILE;
        }
        else if(contact.matches(REGREX_EMAIL)) {
            type = ContactType.EMAIL;
        }
        else
            return false;

        return sendVerificationCode(contact, subject, type);
    }
    /**
     * 发送验证码
     *
     * @param contact 联系方式 手机号/邮箱
     * @param subject 发送标题
     * @return
     */
    @Override
    public boolean sendVerificationCode(String contact, String subject, ContactType contactType) {
        String verificationKey = ( contactType==ContactType.MOBILE
                ? RedisConstants.MOBILE_VERIFICATION_CODE_PREFIX
                : RedisConstants.EMAIL_VERIFICATION_CODE_PREFIX )
                + contact + subject;
        String existCode = redisTemplate.opsForValue().get(verificationKey);

        if(existCode!=null){
            return true;
        }

        // 随机生成6位验证码
        String code = String.valueOf((int) ((Math.random() * 9 + 1) * 100000));
        try {
            // 发送验证码
            switch (contactType) {
                case MOBILE:
                    // 获取修改密码的模板code
                    String templateCode = null;
                    if(subject.equals("绑定手机"))
                        templateCode = aliyunSmsProperties.getTemplateCodes().get("bindMobile");
                    else if(subject.equals("注册新用户"))
                        templateCode = aliyunSmsProperties.getTemplateCodes().get("register");
                    else if(subject.equals("重置密码"))
                        templateCode = aliyunSmsProperties.getTemplateCodes().get("resetPassword");
                    else
                        throw new BusinessException("不支持的短信模板");

                    if(!smsService.sendSms(contact, templateCode, "{\"code\":\"" + code + "\"}"))
                        return false;

                    break;
                case EMAIL:
                    String content = TEMPLATE_MAIL_SENDCODE.replace("${sub}", subject)
                                    .replace("${code}", code);
                    if(!mailService.sendHtmlMail(contact, subject+"验证码", content)){
                        return false;
                    }

                    break;
                default:
                    throw new BusinessException("不支持的联系方式类型");
            }

            // 存入 redis 用于校验, 5分钟有效
            redisTemplate.opsForValue().set(verificationKey, code, 15, TimeUnit.MINUTES);
        }
        catch (Exception e){
            e.printStackTrace();
            return false;
        }

        return true;
    }

    /**
     * 修改当前用户手机号码
     *
     * @param data 表单数据
     * @return
     */
    @Override
    public boolean bindMobile(MobileBindingForm data) {
        Long userId = SecurityUtils.getUserId();
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        // 校验验证码
        String verificationCode = data.getCode();
        String contact = data.getMobile();
        String verificationCodeKey = RedisConstants.MOBILE_VERIFICATION_CODE_PREFIX + contact + "绑定手机";
        String code = redisTemplate.opsForValue().get(verificationCodeKey);
        if (!verificationCode.equals(code)) {
            throw new BusinessException("验证码错误");
        }
        // 更新手机号码
        return accountService.update(new LambdaUpdateWrapper<Account>()
                .eq(Account::getUserId, userId)
                .set(Account::getPhone, contact)
                .set(Account::getIsPhone, 1)
        );
    }

    /**
     * 修改当前用户邮箱
     *
     * @param data 表单数据
     * @return
     */
    @Override
    public boolean bindEmail(EmailChangeForm data) {
        Long userId = SecurityUtils.getUserId();
        User user = this.getById(userId);
        if (user == null) {
            throw new BusinessException("用户不存在");
        }
        // 校验验证码
        String verificationCode = data.getCode();
        String contact = data.getEmail();
        String verificationCodeKey = RedisConstants.EMAIL_VERIFICATION_CODE_PREFIX + contact + "绑定邮箱";
        String code = redisTemplate.opsForValue().get(verificationCodeKey);
        if (!verificationCode.equals(code)) {
            throw new BusinessException("验证码错误");
        }
        // 更新邮箱
        return update(new LambdaUpdateWrapper<User>()
                .eq(User::getId, userId)
                .set(User::getEmail, contact)
                .set(User::getStatus, 2)
        );
    }

    /**
     * 重置密码验证码检验
     *
     * @param contact
     * @param code
     * @return
     */
    @Override
    public int checkVerificationCode(String contact, String code, String title) {
        String verificationKey;
        if( contact.matches(REGREX_PHONE) ) {
            verificationKey = RedisConstants.MOBILE_VERIFICATION_CODE_PREFIX;
        }
        else if(contact.matches(REGREX_EMAIL)) {
            verificationKey = RedisConstants.EMAIL_VERIFICATION_CODE_PREFIX;
        }
        else
            return -3; //参数错误

        verificationKey += contact + title;

        String existCode = redisTemplate.opsForValue().get(verificationKey);
        if (existCode == null) {
            return -2;      //验证码已过期
        }

        return code.equals(existCode) ? 0 : -1; //验证码错误
    }

    @Override
    public RealNameInfo getCurrentRealNameInfo(){
        return realNameService.getCurrentRealName();
    }

    @Override
    public boolean submitRealName(RealNameInfo info){
        boolean result = realNameService.updateById(info);
        if(result){
            result = realNameService.setVerifyRealName(info.getUserId(), 3);
        }

        return result;
    }

    @Override
    public boolean verifyRealName(Long userId, String rejectReason){
        boolean result;
        String title, content;
        if(rejectReason==null || rejectReason.isEmpty()){
            result = realNameService.setVerifyRealName(userId, 1);
            title = "实名认证已通过";
            content = "恭喜您，您申请的 <span style=\"font-size:16px;\">实名认证</span> "
                    + "<b><span style=\"color:#e13c39;font-size:16px;\">已通过</span></b>";
        }
        else {
            result = realNameService.setVerifyRealName(userId, 2);
            title = "实名认证未通过";
            content = "很抱歉，您申请的 <span style=\"font-size:16px;\">实名认证</span> "
                    + "<b><span style=\"color:#e13c39;font-size:16px;\">未通过</span></b>！"
                    + "原因为：<br/>" + rejectReason;
        }

        if(result) {
            messageService.sendUserMessage(userId, title, content);
        }
        return result;
    }

    @Override
    public int beingVIP(Integer vipType) {
        Account account = accountService.getCurrentAccount();
        if(account==null)
            return -1;  //账户异常

        if(account.getState()<2)
            return -2;

        Integer vipTime = account.getVipTime();
        if(vipTime==-1)
            return 0;  //终身VIP

        int pay = 0; //支付音符数
        int nowTime = (int) (System.currentTimeMillis()/1000);
        if(vipTime<nowTime)
            vipTime = nowTime;

        //统一按365.25天/年计算
        switch (vipType){
            case 0:
                pay = 1000;
                vipTime += 2629800;
                break;
            case 1:
                pay = 5500;
                vipTime += 15778800;
                break;
            case 2:
                pay = 10000;
                vipTime += 31557600;
                break;
            case 3:
                pay = 20000;
                vipTime += 63115200;
                break;
            default:
                return -3; //参数异常
        }

        Integer integral = account.getIntegral();
        if(integral<pay)
            return -4; //余额不足

        //先扣除积分
        account.setIntegral(integral - pay);
        account.setVipTime(vipTime);

        if(!accountService.updateById(account) )
            return -5; //数据库异常

        //再写积分明细
        Integral detail = new Integral();
        detail.setUserId(account.getUserId());
        detail.setScore(pay);
        detail.setBalance(account.getIntegral());
        detail.setAddtime(nowTime);
        detail.setTitle("兑换唱作网VIP会员");
        detail.setRuleid(-7);
        detail.setRuletype(2);

        if(!integralService.save(detail))
            return -5; //数据库异常

        //音符消费
        statisticsService.statistics(5,"consume", pay);

        return vipTime;
    }

    @Override
    public Result<?> buyNotes(String payType, String amount) {
        Account account = accountService.getCurrentAccount();
        if(account==null)
            return Result.failed(USER_LOGIN_ERROR);  //账户异常
        if(account.getState()==0)
            return Result.failed(USER_ACCOUNT_DELETED);
        if(account.getState()==1)
            return Result.failed(USER_ACCOUNT_LOCKED);

        String order = orderService.generatorOrderNo(account.getUserId(), payType);
        if( order==null )
            return Result.failed(DATABASE_ERROR);

        return Result.success(order);
    }

    @Override
    public Result<?> drawNotes(DrawQuery draw){
        Account account = accountService.getCurrentAccount();
        if(account==null)
            return Result.failed(USER_LOGIN_ERROR);  //账户异常
        if(account.getState()==0)
            return Result.failed(USER_ACCOUNT_DELETED);
        if(account.getState()==1)
            return Result.failed(USER_ACCOUNT_LOCKED);

        if(account.getIsName()!=1)
            return Result.failed(USER_ACCOUNT_NOREALNAME);

        int amount = draw.getAmount();
        String bankName = draw.getBankName();
        String cardNum = draw.getCardNum();
        if(amount/10000 == 0 || amount % 10000 != 0 || bankName.isEmpty() || cardNum.isEmpty())
            return Result.failed(PARAM_ERROR);

        int integral = account.getIntegral();
        if(integral<amount)
            return Result.failed(USER_ACCOUNT_SHORT);

        String cardName = null;
        if(!bankName.equals("支付宝") && !bankName.equals("微信")){
            cardName = draw.getCardName();
            if(cardName.isEmpty())
                return Result.failed(PARAM_ERROR);
        }

        String money = String.valueOf((amount*94/10000));

        int nowTime = (int)(System.currentTimeMillis()/1000);

        TakeOrder order = new TakeOrder();
        order.setUserId(account.getUserId());
        order.setMoney(money);
        order.setCardNum(cardNum);
        order.setBankName(bankName);
        order.setTakeTime(nowTime);

        if(cardName!=null){
            order.setCardName(cardName);
        }

        if( !takeOrderService.save(order) )
            return Result.failed(DATABASE_ERROR);

        account.setIntegral(integral - amount);

        if(!accountService.updateById(account) )
            return Result.failed(DATABASE_ERROR);

        //积分明细
        Integral detail = new Integral();
        detail.setUserId(account.getUserId());
        detail.setScore(amount);
        detail.setBalance(account.getIntegral());
        detail.setAddtime(nowTime);
        detail.setTitle("银行卡提现：￥" + money);
        detail.setRuleid(-8);
        detail.setRuletype(2);

        if(!integralService.save(detail))
            return Result.failed(DATABASE_ERROR);

        UserBank userBank = userBankService.getById(account.getUserId());
        userBank.setBankName(draw.getBankName());
        userBank.setBankCardNum(draw.getCardNum());
        userBank.setBankCardName(draw.getCardName());

        userBankService.updateById(userBank);

        return Result.success();
    }

    @Override
    public IPage<TakeOrderPageVO> listPageDraw(BasePageQuery queryParams){
        return takeOrderService.listPagedDraw(queryParams);
    }
    @Override
    public int verifyDraw(Integer orderId, String rejectReason){
        TakeOrder order = null;
        String title="", content="";
        if(rejectReason==null || rejectReason.isEmpty()){
            order = takeOrderService.setDrawState(orderId, 1);
            if(order!=null) {
                title = "提现申请已转账";
                content = "您申请的 <span style=\"font-size: 16px;\">￥"
                        + order.getMoney() + "</span> 提现 "
                        + "<strong style=\"color: rgb(225, 60, 57); font-size: 16px;\"> 已转入 </strong>"
                        + "您指定的账户<br/>请注意查收!";
            }
        }
        else {
            order = takeOrderService.setDrawState(orderId, 3);
            if(order!=null) {
                title = "提现申请未通过";
                content = "很抱歉，您申请的 <span style=\"font-size: 16px;\">￥"
                        + order.getMoney() + "</span> 提现 "
                        + "<strong style=\"color: rgb(225, 60, 57); font-size: 16px;\">未能通过</strong> ，原因是：<br/>" + rejectReason;

                Account account = accountService.getById(order.getUserId());
                Integer integral = account.getIntegral();
                int money = Integer.parseInt(order.getMoney());
                int amount = money / 94 * 10000;
                account.setIntegral(integral + amount);
                accountService.updateById(account);

                //写入积分明细
                Integral detail = new Integral();
                detail.setUserId(account.getUserId());
                detail.setScore(amount);
                detail.setBalance(account.getIntegral());
                detail.setAddtime((int)(System.currentTimeMillis()/1000));
                detail.setTitle("提现￥" + money + "未通过退回");
                detail.setRuleid(-8);
                detail.setRuletype(1);
                integralService.save(detail);
            }
        }

        if(order!=null) {
            messageService.sendUserMessage(order.getUserId(), title, content);
            return order.getState();
        }

        return 0;
    }

    @Override
    public Account getCurrentAccount(){
        return accountService.getCurrentAccount();
    }

    @Override
    public Account getAccountById(Long userId){
        return accountService.getById(userId);
    }

    @Override
    public void afterUserLogon(){
        Long userId = SecurityUtils.getUserId();
        Account account = getAccountById(userId);
        Long loginTime = account.getLoginTime();
        long nowTime = System.currentTimeMillis();

        account.setLoginTime(nowTime/1000);
        account.setLoginNum(account.getLoginNum()+1);
        accountService.updateById(account);

        //登录次数
        statisticsService.statistics(5,"login", 1);

        //与上次不是同一天则统计到当天登录人数
        boolean bSameDay = false;
        if(loginTime!=null) {
            Calendar lastCal = Calendar.getInstance(Locale.CHINA);
            Calendar nowCal = Calendar.getInstance(Locale.CHINA);
            lastCal.setTimeInMillis(loginTime * 1000);
            nowCal.setTimeInMillis(nowTime);
            if (lastCal.get(Calendar.YEAR) == nowCal.get(Calendar.YEAR)
                    && lastCal.get(Calendar.MONTH) == nowCal.get(Calendar.MONTH)
                    && lastCal.get(Calendar.DAY_OF_MONTH) == nowCal.get(Calendar.DAY_OF_MONTH)) {
                bSameDay = true;
            }
        }

        if(!bSameDay) {
            statisticsService.statistics(5, "login_usersum", 1);
        }
    }

    @Override
    public boolean existUsername(String username){
        return getOne(new LambdaQueryWrapper<User>().eq(User::getUsername, username))!=null;
    }

    @Override
    public boolean register(String username, String password){
        NewUser user = new NewUser();
        user.setUserName(username);
        user.setPassword(passwordEncoder.encode(password));
        user.setRegTime((int)(System.currentTimeMillis()/1000));

        if(username.matches(REGREX_EMAIL)){
            String nickname = username.split("@")[0];
            if(nickname.length()>20)
                nickname = nickname.substring(0, 20);
            user.setNickname(nickname);
            user.setEmail(username);
            user.setState(2);
        }
        else if(username.matches(REGREX_PHONE)){
            user.setNickname(username);
            user.setPhone(username);
            user.setIsPhone(1);
        }

        boolean ret = newUserService.save(user);
        if(ret){
            statisticsService.statistics(5,"register", 1);
        }

        return ret;
    }

    @Override
    public Integer deleteUser(String username, String password) {
        User user = verifyUser(username, password);
        if(user!=null) {
            Long uid = user.getId();
            user.setStatus(0);
//            user.setUsername("DEL_" + username + "_" + uid);
            if (updateById(user)) {
                Account account = accountService.getById(uid);
                account.setDeleteTime((int)(System.currentTimeMillis()/1000));
                accountService.updateById(account);

                return Math.toIntExact(uid);
            }
        }

        return -1;
    }

    @Override
    public User verifyUser(String username, String password) {
        return getOne(new LambdaQueryWrapper<User>()
                .eq(User::getUsername, username)
                .eq(User::getPassword, passwordEncoder.encode(password)));
    }

    @Override
    public boolean addNotes(Long userId, Integer amount, Integer time){
        Account account = accountService.getById(userId);
        if(account==null)
            return false;

        account.setIntegral( account.getIntegral() + amount );
        if(!accountService.updateById(account))
            return false;

        Integral integral = new Integral();
        integral.setUserId(account.getUserId());
        integral.setScore(amount);
        integral.setBalance(account.getIntegral());
        integral.setTitle("音符充值");
        integral.setRuleid(1);
        integral.setRuletype(5);
        integral.setAddtime(time);

        return integralService.save(integral);
    }

    @Override
    public Integer checkOrder(String orderNo){
        Order order = orderService.getOne(new LambdaQueryWrapper<Order>()
                .eq(Order::getOrderNumber, orderNo));
        if(order==null)
            return -1;

        Long userId = SecurityUtils.getUserId();
        if(!order.getUserId().equals(userId))
            return -1;

        if( order.getState()==0 )
            return 0;

        Account account = accountService.getById(userId);
        if(account==null)
            return -1;

        return account.getIntegral();
    }

    @Override
    public void setNewAccount() {
        Account account = accountService.getCurrentAccount();
        if(account!=null){
            account.setIntegral(12);
            accountService.updateById(account);

            String title = "成功注册唱作网";
            String content = "新用户，您好！<br>感谢加入唱作网，您已获赠12个唱作音符。<br>欢迎使用唱作魔方软件。";
            messageService.sendUserMessage(account.getUserId(), title, content);
        }
    }
}
