package com.ruoyi.frequency.sale.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.code.DictConstant;
import com.ruoyi.code.PublicCommon;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.SysDictData;
import com.ruoyi.common.exception.CustomException;
import com.ruoyi.common.exception.enums.CoreExceptionEnum;
import com.ruoyi.common.page.PageResult;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.controller.req.RegisterUserReq;
import com.ruoyi.controller.req.SaleDetailPageReq;
import com.ruoyi.controller.req.UserEditReqVo;
import com.ruoyi.controller.resp.RankingResp;
import com.ruoyi.controller.resp.SaleDetailPageResp;
import com.ruoyi.enums.PlatformRecordEnums;
import com.ruoyi.enums.WalletDetailEnums;
import com.ruoyi.enums.user.UserEnums;
import com.ruoyi.frequency.customer.service.UserService;
import com.ruoyi.frequency.platformrecord.service.PlatformRecordService;
import com.ruoyi.frequency.sale.entity.Sale;
import com.ruoyi.frequency.sale.mapper.SaleMapper;
import com.ruoyi.frequency.sale.model.result.SaleCount;
import com.ruoyi.frequency.sale.service.SaleService;
import com.ruoyi.frequency.wallerecord.service.WalletRecordService;
import com.ruoyi.response.ResponseData;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.utils.BusinessUtil;
import com.ruoyi.utils.SnowIdUtils;
import com.ruoyi.utils.pwd.MD5EncryptionPwdUtil;
import com.ruoyi.vo.PageBasic;
import com.ruoyi.vo.UserInfo;
import com.ruoyi.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 销售账号Service业务层处理
 *
 * @author zj
 * @date 2023-09-22
 */
@Service
public class SaleServiceImpl extends ServiceImpl<SaleMapper, Sale> implements SaleService {
    @Autowired
    private SaleMapper saleMapper;

    @Autowired
    private BusinessUtil businessUtil;

    /**
     * 查询销售账号
     *
     * @param id 销售账号主键
     * @return 销售账号
     */
    @Override
    public Sale selectSaleById(Long id) {
        return saleMapper.selectSaleById(id);
    }

    /**
     * 查询销售账号列表
     *
     * @param sale 销售账号
     * @return 销售账号
     */
    @Override
    public List<Sale> selectSaleList(Sale sale) {
        return saleList(sale);
    }

    private List<Sale> saleList(Sale sale) {
        return saleMapper.selectSaleList(sale);
    }

    @Override
    public SaleCount statistics(Sale sale) {
        List<Sale> sales = selectSaleList(sale);
        List<Long> saleIdList = sales.stream().map(x -> x.getId()).collect(Collectors.toList());
        saleIdList.add(-1L);

        return saleMapper.statistics(saleIdList);
    }

    @Autowired
    private ISysConfigService configService;

    /**
     * 新增销售账号
     *
     * @param sale 销售账号
     * @return 结果
     */
    @Override
    public int insertSale(Sale sale) {

        if (ObjectUtil.isEmpty(sale.getLoginPwd())) {
            String password = configService.selectConfigByKey("sys.user.initPassword");
            sale.setLoginPwd(password);
        }
        //MD5加密
        String md5Pwd = MD5EncryptionPwdUtil.encryptionMd5(sale.getLoginPwd());

        //账号验证
        Sale saleExit = this.getBaseMapper().selectOne(Wrappers.<Sale>lambdaQuery().
                eq(Sale::getMobile, sale.getMobile()).ne(Sale::getDelFlag, PublicCommon.删除));
        if (saleExit != null) {
            throw new CustomException(CoreExceptionEnum.PHONE_HAS_EXIST);
        }
        //组装用户
        RegisterUserReq req = new RegisterUserReq();
        req.setMobile(sale.getMobile());
        Sale insertSale = this.assembleSale(req, md5Pwd);
        insertSale.setAvatar(sale.getAvatar());
        insertSale.setName(sale.getName());
        //生成邀请码
        String saleInvitationCode = refereeUserCode(6);
        insertSale.setInviteCode(saleInvitationCode);
        insertSale.setSignature(sale.getSignature());
        insertSale.setEnterDate(sale.getEnterDate());
        insertSale.setBank(sale.getBank());
        insertSale.setSubbranch(sale.getSubbranch());
        insertSale.setBankCard(sale.getBankCard());

        return saleMapper.insert(insertSale);
    }

    /**
     * 生成普通用户验证码
     *
     * @param codeLength 编码长度
     * @return 验证码字符窜
     */
    private String refereeUserCode(int codeLength) {
        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++;
                }
            }
            Sale sale = this.getBaseMapper().selectOne(new QueryWrapper<Sale>().lambda()
                    .eq(Sale::getInviteCode, pwd.toString()));
            if (sale == null) {
                isHave = false;
            }
            count = 0;
        }
        return pwd.toString();
    }


    /**
     * 修改销售账号
     *
     * @param sale 销售账号
     * @return 结果
     */
    @Override
    public int updateSale(Sale sale) {

        //账号验证
        Sale saleExit = this.getBaseMapper().selectOne(Wrappers.<Sale>lambdaQuery().
                eq(Sale::getMobile, sale.getMobile())
                .ne(Sale::getId, sale.getId())
                .ne(Sale::getDelFlag, PublicCommon.删除));
        if (saleExit != null) {
            throw new CustomException(CoreExceptionEnum.PHONE_HAS_EXIST);
        }

        sale.setUpdateTime(DateUtils.getNowDate());

        if (ObjectUtil.isNotEmpty(sale.getLoginPwd())) {
            sale.setLoginPwd(MD5EncryptionPwdUtil.encryptionMd5(sale.getLoginPwd()));
        }
        return saleMapper.updateById(sale);
    }

    /**
     * 批量删除销售账号
     *
     * @param ids 需要删除的销售账号主键
     * @return 结果
     */
    @Override
    public int deleteSaleByIds(Long[] ids, Integer delFlag) {
        this.lambdaUpdate().set(Sale::getDelFlag, delFlag).in(Sale::getId, ids).update();
        return ids.length;
    }

    /**
     * 删除销售账号信息
     *
     * @param id 销售账号主键
     * @return 结果
     */
    @Override
    public int deleteSaleById(Long id) {
        return saleMapper.deleteSaleById(id);
    }

    @Autowired
    private WalletRecordService walletRecordService;

    @Autowired
    private PlatformRecordService platformRecordService;

    @Override
    public AjaxResult updateBalance(Sale sale) {

        BigDecimal price = sale.getBalance();

        //修改余额
        if (price.compareTo(BigDecimal.ZERO) > 0) {
            walletRecordService.updateBalance(new UserVo(UserEnums.sale.getCode(), sale.getId()), WalletDetailEnums.PLAT_ADD, sale.getRemark(), sale.getId(), price, PublicCommon.Wallet.可提现);

            //平台流水
            platformRecordService.addPlatformRecord(new UserVo(UserEnums.sale.getCode(), sale.getId()), sale.getId(), price.negate(), PlatformRecordEnums.PLAT_ADD);

        } else if (price.compareTo(BigDecimal.ZERO) < 0) {
            walletRecordService.updateBalance(new UserVo(UserEnums.sale.getCode(), sale.getId()), WalletDetailEnums.PLAT_SUB, sale.getRemark(), sale.getId(), price, PublicCommon.Wallet.可提现);

            //平台流水
            platformRecordService.addPlatformRecord(new UserVo(UserEnums.sale.getCode(), sale.getId()), sale.getId(), price, PlatformRecordEnums.PLAT_ADD);

        }


        return AjaxResult.success();
    }

    @Override
    public ResponseData editInfo(UserEditReqVo vo, UserVo userVo) {

        LambdaUpdateChainWrapper<Sale> lambdaUpdate = this.lambdaUpdate();
        lambdaUpdate.set(Sale::getId, userVo.getUserId());
        //头像
        if (ObjectUtil.isNotEmpty(vo.getAvatar())) {
            lambdaUpdate.set(Sale::getAvatar, vo.getAvatar());
        }
        //入行时间
        if (ObjectUtil.isNotEmpty(vo.getEnterDate())) {
            lambdaUpdate.set(Sale::getEnterDate, DateUtil.parse(vo.getEnterDate(), "yyyy"));
        }
        //背景图
        if (ObjectUtil.isNotEmpty(vo.getBackgroundImage())) {
            lambdaUpdate.set(Sale::getBackgroundImage, vo.getBackgroundImage());
        }

        if (ObjectUtil.isNotEmpty(vo.getSignature())) {
            lambdaUpdate.set(Sale::getSignature, vo.getSignature());
        }

        //推送是否关闭;1不关闭2  关闭
        if (ObjectUtil.isNotEmpty(vo.getCloseMessage())) {
            lambdaUpdate.set(Sale::getCloseMessage, vo.getCloseMessage());
        }

        //条件
        lambdaUpdate.eq(Sale::getId, userVo.getUserId()).update();

        return ResponseData.success();
    }

    @Override
    public ResponseData info(UserVo userVo) {

        final Sale sale = this.baseMapper.selectSaleById(userVo.getUserId());

        return ResponseData.success(sale);
    }

    @Override
    public Sale assembleSale(RegisterUserReq req, String md5Pwd) {
        Sale sale = new Sale();
        sale.setId(SnowIdUtils.uniqueLong());

        //手机号
        sale.setMobile(req.getMobile());

        //默认头像
        SysDictData dict = businessUtil.getDict(DictConstant.默认头像);
        sale.setAvatar(dict.getImages());

        Sale maxSale = this.getOne(new QueryWrapper<Sale>().lambda().orderByDesc(Sale::getNickname).last("limit 1"));

        Integer num = maxSale == null ? 0 : Integer.valueOf(maxSale.getNickname().replace("TGY", ""));

        sale.setNickname(getNickname(num));
        sale.setLoginPwd(md5Pwd);
        sale.setCreateTime(new Date());
        sale.setUpdateTime(new Date());

        return sale;
    }

    private String getNickname(Integer num) {
        String template = "TGY%06d";
        num++;
        String id = String.format(template, num);
        return id;
    }

    @Override
    public Integer commissionRanking(UserVo userVo) {
        return saleMapper.commissionRanking(userVo.getUserId());
    }

    @Override
    public Integer saleRanking(UserVo userVo) {
        return saleMapper.saleRanking(userVo.getUserId());
    }

    @Override
    public ResponseData<PageResult<Page<RankingResp>>> commissionRankingPage(PageBasic req, UserVo userVo) {
        Page<RankingResp> page = saleMapper.commissionRankingPage(new Page<>(req.getPageNo(), req.getPageSize()), userVo.getUserId());
        if (!page.getRecords().isEmpty()) {
            Integer i = (req.getPageNo() - 1) * req.getPageSize() + 1;
            for (RankingResp record : page.getRecords()) {
                record.setRanking(i++);
            }
        }

        return ResponseData.success(new PageResult<>(page));
    }

    @Override
    public ResponseData<PageResult<Page<RankingResp>>> saleRankingPage(PageBasic req, UserVo userVo) {
        Page<RankingResp> page = saleMapper.saleRankingPage(new Page<>(req.getPageNo(), req.getPageSize()), userVo.getUserId());
        if (!page.getRecords().isEmpty()) {
            Integer i = (req.getPageNo() - 1) * req.getPageSize() + 1;
            for (RankingResp record : page.getRecords()) {
                record.setRanking(i++);
            }
        }
        return ResponseData.success(new PageResult<>(page));
    }

    @Autowired
    private UserService userService;

    @Override
    public ResponseData<PageResult<Page<SaleDetailPageResp>>> saleDetailPage(SaleDetailPageReq req, UserVo userVo) {
        Page<SaleDetailPageResp> page = saleMapper.saleDetailPage(new Page<>(req.getPageNo(), req.getPageSize()), req, userVo.getUserId());

        if (!page.getRecords().isEmpty()) {

            Set<UserVo> userVoSet = new HashSet<>();
            page.getRecords().stream().forEach(orderPageResp -> {
                userVoSet.add(new UserVo(UserEnums.customer.getCode(), orderPageResp.getCustomerId()));
                userVoSet.add(new UserVo(UserEnums.store.getCode(), orderPageResp.getStoreId()));
            });

            //查询用户信息
            Map<UserVo, UserInfo> userMap = userService.selectUserInfoMap(userVoSet, userVo);

            page.getRecords().stream().forEach(orderPageResp -> {
                orderPageResp.setCustomerInfo(userMap.get(new UserVo(UserEnums.customer.getCode(), orderPageResp.getCustomerId())));
                orderPageResp.setStoreInfo(userMap.get(new UserVo(UserEnums.store.getCode(), orderPageResp.getStoreId())));
            });

        }

        return ResponseData.success(new PageResult<>(page));
    }
}
