package com.ruoyi.utils;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.code.DictConstant;
import com.ruoyi.code.PublicCommon;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.enums.CoreExceptionEnum;
import com.ruoyi.controller.req.LoginReqVo;
import com.ruoyi.controller.req.RegisterUserReq;
import com.ruoyi.enums.IntegralDetailEnums;
import com.ruoyi.enums.LoginEnums;
import com.ruoyi.enums.WalletDetailEnums;
import com.ruoyi.enums.user.UserEnums;
import com.ruoyi.frequency.customer.entity.Customer;
import com.ruoyi.frequency.customer.service.CustomerService;
import com.ruoyi.frequency.givewallerecord.service.GiveWalletRecordService;
import com.ruoyi.frequency.integralrecord.service.IntegralRecordService;
import com.ruoyi.frequency.refereeuser.entity.RefereeUser;
import com.ruoyi.frequency.refereeuser.mapper.RefereeUserMapper;
import com.ruoyi.frequency.sale.entity.Sale;
import com.ruoyi.frequency.sale.service.SaleService;
import com.ruoyi.frequency.store.entity.Store;
import com.ruoyi.frequency.store.service.StoreService;
import com.ruoyi.utils.pwd.MD5EncryptionPwdUtil;
import com.ruoyi.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;
import java.util.Random;

/**
 * @Author liwenlong
 */

@Component
public class JudgeLogicUtil {

    @Autowired
    private CustomerService customerService;

    @Autowired
    private StoreService storeService;

    @Autowired
    private SaleService saleService;

    /**
     * 验证登入账号
     *
     * @return
     */
    public Long checkLoginUser(LoginReqVo loginReqVo) {
        switch (UserEnums.getUserEnums(loginReqVo.getUserType())) {
            case customer:
                Customer customer = getCustomer(loginReqVo);
                //逻辑判断
                return judgeCustomer(customer, loginReqVo);
            case store:
                Store store = getStore(loginReqVo);
                //逻辑判断
                return judgeStore(store, loginReqVo);
            case sale:
                Sale sale = getSale(loginReqVo);
                //逻辑判断
                return judgeSale(sale, loginReqVo);
            default:
                return null;
        }
    }

    private final List<LoginEnums> assembleEnums = CollectionUtil.toList(LoginEnums.code_login, LoginEnums.one_click_login, LoginEnums.wechat_login, LoginEnums.applet_login, LoginEnums.apple_login);

    /**
     * 判断用户
     *
     * @param customer
     */
    private Long judgeCustomer(Customer customer, LoginReqVo loginReqVo) {

        LoginEnums loginEnums = LoginEnums.getLoginEnums(loginReqVo.getType());

        if (customer == null && !assembleEnums.contains(loginEnums)) {
            throw new CustomException(CoreExceptionEnum.ACCOUNT_NOT_EXIST);
        }

        RegisterUserReq registerReq = new RegisterUserReq(loginReqVo);

        String md5Pwd = null;
        //MD5加密
        if (ObjectUtil.isNotEmpty(loginReqVo.getPassword())) {
            md5Pwd = MD5EncryptionPwdUtil.encryptionMd5(loginReqVo.getPassword());
        }

        if (customer == null && assembleEnums.contains(loginEnums)) {

            switch (loginEnums) {
                case one_click_login:
                    //组装用户
                    customer = customerService.assembleCustomer(registerReq, md5Pwd);

                    //生成邀请码
                    String invitationCode = refereeUserCode(6, UserEnums.customer.getCode());
                    customer.setInvitationCode(invitationCode);
                    customerService.getBaseMapper().insert(customer);
                    //创建绑定关系
                    bindParentUser(customer.getId(), UserEnums.customer.getCode(), loginReqVo.getInvitationCode());
                    break;
                default:

                    //微信，小程序，苹果登入需要绑定手机号（排除一键登入）
                    if (ObjectUtil.isEmpty(loginReqVo.getMobile()) && ObjectUtil.isNotEmpty(loginReqVo.getAccount())) {
                        loginReqVo.setMobile(loginReqVo.getAccount());
                    }
                    if (ObjectUtil.isEmpty(loginReqVo.getMobile())) {
                        throw new CustomException(710, "请绑定手机号");
                    }

                    //根据手机号查询用户
                    customer = customerService.getOne(new QueryWrapper<Customer>().lambda()
                            .eq(Customer::getAreaCode, loginReqVo.getAreaCode())
                            .eq(Customer::getMobile, loginReqVo.getMobile())
                            .ne(Customer::getDelFlag, PublicCommon.删除));

                    if (customer != null) {
                        Long userId = customer.getId();
                        customer = new Customer().setId(userId);
                    } else {
                        //组装用户
                        customer = customerService.assembleCustomer(registerReq, md5Pwd);

                        //生成邀请码
                        invitationCode = refereeUserCode(6, UserEnums.customer.getCode());
                        customer.setInvitationCode(invitationCode);
                        customerService.getBaseMapper().insert(customer);
                        //创建绑定关系
                        bindParentUser(customer.getId(), UserEnums.customer.getCode(), loginReqVo.getInvitationCode());
                    }

                    switch (loginEnums) {
                        case wechat_login:
                            customer.setWechatOpenid(loginReqVo.getOpenid());
                            break;
                        case applet_login:
                            customer.setWechatAppletOpenid(loginReqVo.getOpenid());
                            customer.setUnionId(loginReqVo.getUnionid());
                            break;
                        case apple_login:
                            customer.setAppleOpenid(loginReqVo.getOpenid());
                            break;
                    }
            }
            customerService.getBaseMapper().updateById(customer);
            //customerService.saveOrUpdate(customer);

        } else if (customer.getDelFlag().equals(PublicCommon.禁用)) {
            throw new CustomException(CoreExceptionEnum.ACCOUNT_DISABLE);
        }
        //修改clientId
        customerService.lambdaUpdate().set(Customer::getClientId, loginReqVo.getClientId()).eq(Customer::getId, customer.getId()).update();
        return customer.getId();
    }

    /**
     * 生成普通用户验证码
     *
     * @param codeLength 编码长度
     * @return 验证码字符窜
     */
    public String refereeUserCode(int codeLength, Integer userType) {
        int i;
        int count = 0;
//        char[] str = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
//                '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
//                'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
//                'Z'};
        char[] str = {'0', '1', '2', '3', '4', '5', '6', '7', '8',
                '9'};
        StringBuffer pwd = new StringBuffer("");
        Random r = new Random();
        boolean isHave = true;
        while (isHave) {
            while (count < codeLength) {
                i = Math.abs(r.nextInt(str.length));
                if (i >= 0 && i < str.length) {
                    pwd.append(str[i]);
                    count++;
                }
            }

            if (ObjectUtil.equal(UserEnums.customer.getCode(), userType)) {
                Customer customer = customerService.getBaseMapper().selectOne(new QueryWrapper<Customer>().lambda()
                        .eq(Customer::getInvitationCode, pwd.toString()));
                if (customer == null) {
                    isHave = false;
                }
            } else if (ObjectUtil.equal(UserEnums.store.getCode(), userType)) {
                Store store = storeService.getBaseMapper().selectOne(new QueryWrapper<Store>().lambda()
                        .eq(Store::getInvitationCode, pwd.toString()));
                if (store == null) {
                    isHave = false;
                }
            } else if (ObjectUtil.equal(UserEnums.sale.getCode(), userType)) {
                Sale sale = saleService.getBaseMapper().selectOne(new QueryWrapper<Sale>().lambda()
                        .eq(Sale::getInviteCode, pwd.toString()));
                if (sale == null) {
                    isHave = false;
                }
            } else {
                isHave = false;
            }

            count = 0;
        }
        return pwd.toString();
    }

    @Autowired
    private RefereeUserMapper refereeUserMapper;

    @Autowired
    private BusinessUtil businessUtil;

    @Autowired
    private GiveWalletRecordService giveWalletRecordService;

    @Autowired
    private IntegralRecordService integralRecordService;

    /**
     * @param userId
     * @param userType
     * @param invitationCode
     */
    private void bindParentUser(Long userId, Integer userType, String invitationCode) {
        if (StrUtil.isBlank(invitationCode)) {
            return;
        }
        Customer customer = customerService.getOne(new QueryWrapper<Customer>().lambda().eq(Customer::getInvitationCode, invitationCode));
        if (customer != null) {
            RefereeUser refereeUser = new RefereeUser();
            refereeUser.setUserId(userId);
            refereeUser.setUserType(userType);
            refereeUser.setParentUserId(customer.getId());
            refereeUser.setParentUserType(UserEnums.customer.getCode());
            refereeUserMapper.insert(refereeUser);

            //被注册赠送抵用金
            sendGiveBalance(userType,userId,refereeUser.getId());

            //查询字典配置的赠送抵积分
            SysDictData dict = businessUtil.getDict(DictConstant.注册赠送积分);

            if (dict != null) {
                BigDecimal integral = new BigDecimal(dict.getDictValue());
                //积分记录
                integralRecordService.updateIntegral(new UserVo(refereeUser.getParentUserType(), refereeUser.getParentUserId()), null, integral, IntegralDetailEnums.REFEREE_SEND,null);
            }
        } else {
            Store store = storeService.getOne(new QueryWrapper<Store>().lambda().eq(Store::getInvitationCode, invitationCode));
            if (store != null) {
                RefereeUser refereeUser = new RefereeUser();
                refereeUser.setUserId(userId);
                refereeUser.setUserType(userType);
                refereeUser.setParentUserId(store.getId());
                refereeUser.setParentUserType(UserEnums.store.getCode());
                refereeUserMapper.insert(refereeUser);

                //被注册赠送抵用金
                sendGiveBalance(userType,userId,refereeUser.getId());

            } else {
                Sale sale = saleService.getOne(new QueryWrapper<Sale>().lambda().eq(Sale::getInviteCode, invitationCode));
                if (sale != null) {
                    RefereeUser refereeUser = new RefereeUser();
                    refereeUser.setUserId(userId);
                    refereeUser.setUserType(userType);
                    refereeUser.setParentUserId(sale.getId());
                    refereeUser.setParentUserType(UserEnums.sale.getCode());
                    refereeUserMapper.insert(refereeUser);


                    //被注册赠送抵用金
                    sendGiveBalance(userType,userId,refereeUser.getId());

                    //销售修改邀请数量
                    saleService.lambdaUpdate().setSql("invite_num=invite_num+1").eq(Sale::getId, refereeUser.getParentUserId()).update();
                }
            }
        }
    }

    /**
     * 被邀请注册赠送抵用金
     * @param userType
     * @param userId
     * @param refereeId
     */
    private void sendGiveBalance(Integer userType,Long userId,Long refereeId){
        if(userType!=null && userType.equals(UserEnums.customer.getCode())){
            //查询字典配置的赠送抵用金
            SysDictData dict = businessUtil.getDict(DictConstant.注册赠送抵用金);

            if (dict != null) {
                BigDecimal giveAmount = new BigDecimal(dict.getDictValue());
                //钱包记录
                giveWalletRecordService.updateGiveBalance(new UserVo(userType, userId), WalletDetailEnums.GIVE_BALANCE, refereeId, giveAmount, PublicCommon.Wallet.可提现);
            }
        }
    }

    /**
     * 判断用户
     *
     * @param store
     */
    private Long judgeStore(Store store, LoginReqVo loginReqVo) {

        LoginEnums loginEnums = LoginEnums.getLoginEnums(loginReqVo.getType());

        if (store == null && !assembleEnums.contains(loginEnums)) {
            throw new CustomException(CoreExceptionEnum.ACCOUNT_NOT_EXIST);
        }

        RegisterUserReq registerReq = new RegisterUserReq(loginReqVo);

        String md5Pwd = null;
        //MD5加密
        if (ObjectUtil.isNotEmpty(loginReqVo.getPassword())) {
            md5Pwd = MD5EncryptionPwdUtil.encryptionMd5(loginReqVo.getPassword());
        }


        if (store == null && assembleEnums.contains(loginEnums)) {

            switch (loginEnums) {
                case one_click_login:
                    //组装用户
                    store = storeService.assembleStore(registerReq, md5Pwd);
                    //生成邀请码
                    String invitationCode = refereeUserCode(6, UserEnums.store.getCode());
                    store.setInvitationCode(invitationCode);
                    //创建绑定关系
                    bindParentUser(store.getId(), UserEnums.store.getCode(), loginReqVo.getInvitationCode());
                    break;
                default:
                    if (ObjectUtil.isEmpty(loginReqVo.getMobile()) && ObjectUtil.isNotEmpty(loginReqVo.getAccount())) {
                        loginReqVo.setMobile(loginReqVo.getAccount());
                    }
                    //微信，小程序，苹果登入需要绑定手机号（排除一键登入）
                    if (ObjectUtil.isEmpty(loginReqVo.getMobile())) {
                        throw new CustomException(710, "请绑定手机号");
                    }

                    //根据手机号查询用户
                    store = storeService.getOne(new QueryWrapper<Store>().lambda()
                            .eq(Store::getMobile, loginReqVo.getMobile())
                            .ne(Store::getDelFlag, PublicCommon.删除));

                    if (store != null) {
                        Long userId = store.getId();
                        store = new Store().setId(userId);
                    } else {
                        //组装用户
                        store = storeService.assembleStore(registerReq, md5Pwd);
                        //生成邀请码
                        invitationCode = refereeUserCode(6, UserEnums.store.getCode());
                        store.setInvitationCode(invitationCode);
                        //创建绑定关系
                        bindParentUser(store.getId(), UserEnums.store.getCode(), loginReqVo.getInvitationCode());
                    }

                    switch (loginEnums) {
                        case wechat_login:
                            store.setWechatOpenid(loginReqVo.getOpenid());
                            break;
                        case applet_login:
                            store.setWechatAppletOpenid(loginReqVo.getOpenid());
                            store.setUnionId(loginReqVo.getUnionid());
                            break;
                        case apple_login:
                            store.setAppleOpenid(loginReqVo.getOpenid());
                            break;
                    }
            }
            storeService.saveOrUpdate(store);

        } else if (store.getDelFlag().equals(PublicCommon.禁用)) {
            throw new CustomException(CoreExceptionEnum.ACCOUNT_DISABLE);
        }
        //修改clientId
//        storeService.lambdaUpdate().set(Store::getClientId,loginReqVo.getClientId()).eq(Store::getId,store.getId()).update();
        return store.getId();
    }


    /**
     * 判断用户
     *
     * @param sale
     */
    private Long judgeSale(Sale sale, LoginReqVo loginReqVo) {

        LoginEnums loginEnums = LoginEnums.getLoginEnums(loginReqVo.getType());

        if (sale == null && !assembleEnums.contains(loginEnums)) {
            throw new CustomException(CoreExceptionEnum.ACCOUNT_NOT_EXIST);
        }

        RegisterUserReq registerReq = new RegisterUserReq(loginReqVo);

        String md5Pwd = null;
        //MD5加密
        if (ObjectUtil.isNotEmpty(loginReqVo.getPassword())) {
            md5Pwd = MD5EncryptionPwdUtil.encryptionMd5(loginReqVo.getPassword());
        }

        if (sale == null && assembleEnums.contains(loginEnums)) {

            switch (loginEnums) {
                case one_click_login:
                    //组装用户
                    sale = saleService.assembleSale(registerReq, md5Pwd);

                    //生成邀请码
                    String invitationCode = refereeUserCode(6, UserEnums.sale.getCode());
                    sale.setInviteCode(invitationCode);
                    //创建绑定关系
                    bindParentUser(sale.getId(), UserEnums.sale.getCode(), loginReqVo.getInvitationCode());
                    break;
                default:
                    if (ObjectUtil.isEmpty(loginReqVo.getMobile()) && ObjectUtil.isNotEmpty(loginReqVo.getAccount())) {
                        loginReqVo.setMobile(loginReqVo.getAccount());
                    }
                    //微信，小程序，苹果登入需要绑定手机号（排除一键登入）
                    if (ObjectUtil.isEmpty(loginReqVo.getMobile())) {
                        throw new CustomException(710, "请绑定手机号");
                    }

                    //根据手机号查询用户
                    sale = saleService.getOne(new QueryWrapper<Sale>().lambda()
                            .eq(Sale::getMobile, loginReqVo.getAccount())
                            .ne(Sale::getDelFlag, PublicCommon.删除));

                    if (sale != null) {
                        Long userId = sale.getId();
                        sale = new Sale().setId(userId);
                    } else {
                        //组装用户
                        sale = saleService.assembleSale(registerReq, md5Pwd);

                        //生成邀请码
                        invitationCode = refereeUserCode(6, UserEnums.sale.getCode());
                        sale.setInviteCode(invitationCode);
                        //创建绑定关系
                        bindParentUser(sale.getId(), UserEnums.sale.getCode(), loginReqVo.getInvitationCode());
                    }

                    switch (loginEnums) {
                        case wechat_login:
                            sale.setWechatOpenid(loginReqVo.getOpenid());
                            break;
                        case applet_login:
                            sale.setWechatAppletOpenid(loginReqVo.getOpenid());
                            sale.setUnionId(loginReqVo.getOpenid());
                            break;
                        case apple_login:
                            sale.setAppleOpenid(loginReqVo.getOpenid());
                            break;
                    }
            }
            saleService.saveOrUpdate(sale);

        } else if (sale.getDelFlag().equals(PublicCommon.禁用)) {
            throw new CustomException(CoreExceptionEnum.ACCOUNT_DISABLE);
        }
        //修改clientId
//        storeService.lambdaUpdate().set(Store::getClientId,loginReqVo.getClientId()).eq(Store::getId,store.getId()).update();
        return sale.getId();
    }


    /**
     * 获取用户
     *
     * @return
     */
    private Customer getCustomer(LoginReqVo loginReqVo) {

        LambdaQueryWrapper<Customer> lambda = new QueryWrapper<Customer>()
                .lambda()
                .ne(Customer::getDelFlag, PublicCommon.删除);

        switch (LoginEnums.getLoginEnums(loginReqVo.getType())) {
            case code_login:
                lambda.eq(Customer::getAccount, loginReqVo.getAccount());
                break;
            case pwd_login:
                lambda.eq(Customer::getMobile, loginReqVo.getAccount());
                break;
            case one_click_login:
                lambda.eq(Customer::getMobile, loginReqVo.getMobile());
                break;
            case wechat_login:
                lambda.eq(Customer::getWechatOpenid, loginReqVo.getOpenid());
                break;
            case applet_login:
                lambda.eq(Customer::getWechatAppletOpenid, loginReqVo.getOpenid());
                break;
            case apple_login:
                lambda.eq(Customer::getAppleOpenid, loginReqVo.getOpenid());
                break;
        }
        Customer customer = customerService.getOne(lambda);

        return customer;
    }

    private Store getStore(LoginReqVo loginReqVo) {

        LambdaQueryWrapper<Store> lambda = new QueryWrapper<Store>()
                .lambda()
                .ne(Store::getDelFlag, PublicCommon.删除);

        switch (LoginEnums.getLoginEnums(loginReqVo.getType())) {
            case code_login:
                lambda.eq(Store::getAccount, loginReqVo.getAccount());
                break;
            case pwd_login:
                lambda.eq(Store::getAccount, loginReqVo.getAccount());
                break;
            case one_click_login:
                lambda.eq(Store::getMobile, loginReqVo.getMobile());
                break;
            case wechat_login:
                lambda.eq(Store::getWechatOpenid, loginReqVo.getOpenid());
                break;
            case applet_login:
                lambda.eq(Store::getWechatAppletOpenid, loginReqVo.getOpenid());
                break;
            case apple_login:
                lambda.eq(Store::getAppleOpenid, loginReqVo.getOpenid());
                break;
        }
        Store store = storeService.getOne(lambda);

        return store;
    }

    private Sale getSale(LoginReqVo loginReqVo) {

        LambdaQueryWrapper<Sale> lambda = new QueryWrapper<Sale>()
                .lambda()
                .ne(Sale::getDelFlag, PublicCommon.删除);

        switch (LoginEnums.getLoginEnums(loginReqVo.getType())) {
            case code_login:
                lambda.eq(Sale::getMobile, loginReqVo.getAccount());
                break;
            case pwd_login:
                lambda.eq(Sale::getMobile, loginReqVo.getAccount());
                break;
            case one_click_login:
                lambda.eq(Sale::getMobile, loginReqVo.getAccount());
                break;
            case wechat_login:
                lambda.eq(Sale::getWechatOpenid, loginReqVo.getOpenid());
                break;
            case applet_login:
                lambda.eq(Sale::getWechatAppletOpenid, loginReqVo.getOpenid());
                break;
            case apple_login:
                lambda.eq(Sale::getAppleOpenid, loginReqVo.getOpenid());
                break;
        }
        Sale sale = saleService.getOne(lambda);

        return sale;
    }


}
