package cn.ysk.cashier.service.impl.shopimpl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.ysk.cashier.dto.shop.TbShopRechargeListDto;
import cn.ysk.cashier.dto.shop.TbShopRechargeRespDto;
import cn.ysk.cashier.dto.shop.TbShopUserDto;
import cn.ysk.cashier.dto.shop.TbShopUserQueryCriteria;
import cn.ysk.cashier.exception.BadRequestException;
import cn.ysk.cashier.mapper.shop.TbShopUserMapper;
import cn.ysk.cashier.mybatis.entity.TbShopUserFlow;
import cn.ysk.cashier.mybatis.mapper.ShopUserMapper;
import cn.ysk.cashier.mybatis.mapper.TbShopUserFlowMapper;
import cn.ysk.cashier.pojo.shop.TbShopUser;
import cn.ysk.cashier.repository.order.TbOrderInfoRepository;
import cn.ysk.cashier.repository.shop.TbShopUserRepository;
import cn.ysk.cashier.service.shop.TbShopUserService;
import cn.ysk.cashier.utils.FileUtil;
import cn.ysk.cashier.utils.PageUtil;
import cn.ysk.cashier.utils.QueryHelp;
import cn.ysk.cashier.utils.ValidationUtil;
import cn.ysk.cashier.vo.ShopUserInfoVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.Instant;
import java.util.*;

/**
 * @author lyf
 * @website https://eladmin.vip
 * @description 服务实现
 * @date 2024-03-01
 **/
@Service
@RequiredArgsConstructor
public class TbShopUserServiceImpl implements TbShopUserService {

    private final TbShopUserRepository tbShopUserRepository;
    private final TbShopUserMapper tbShopUserMapper;

    private final TbOrderInfoRepository tbOrderInfoRepository;

    @Autowired
    private ShopUserMapper shopUserMapper;

    @Autowired
    private TbShopUserFlowMapper tbShopUserFlowMapper;


    @Override
    public Map<String, Object> queryShopUser(TbShopUserQueryCriteria criteria) {
        IPage<ShopUserInfoVo> iPage = shopUserMapper.queryUser(criteria, criteria.getIsVip(),
                new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(criteria.getPage(), criteria.getSize()));

        for (ShopUserInfoVo shopUserInfoVo : iPage.getRecords()) {
            if (StrUtil.isBlank(shopUserInfoVo.getNickName())) {
                tbShopUserRepository.findById(shopUserInfoVo.getId()).ifPresent(tbShopUser -> {
                    shopUserInfoVo.setNickName(tbShopUser.getName());
                    shopUserInfoVo.setBirthDay(tbShopUser.getBirthDay());
                    shopUserInfoVo.setHeadImg(tbShopUser.getHeadImg());
                    shopUserInfoVo.setTelephone(tbShopUser.getTelephone());
                    shopUserInfoVo.setTotalScore(0);
                });
            }

            if (shopUserInfoVo.getUserId() == null) {
                shopUserInfoVo.setUserId(0);
                shopUserInfoVo.setOrderNumber(0);
            } else {
                Integer orderNumber = tbOrderInfoRepository.countByUserIdAndStatusAndShopId(shopUserInfoVo.getUserId().toString(), criteria.getShopId());
                shopUserInfoVo.setOrderNumber(Objects.isNull(orderNumber) ? 0 : orderNumber);
            }
            shopUserInfoVo.setInMoney(tbShopUserRepository.sumAmount(shopUserInfoVo.getId()));
        }

        return PageUtil.toPlusPage(iPage.getRecords(), Integer.valueOf(iPage.getTotal() + ""));
    }

    @Override
    public Map<String, Object> queryAll(TbShopUserQueryCriteria criteria, Pageable pageable) {
        criteria.setIsVip(1);
        Page<TbShopUser> page = tbShopUserRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder), pageable);
        return PageUtil.toPage(page.map(tbShopUserMapper::toDto));
    }

    @Override
    public List<TbShopUserDto> queryAll(TbShopUserQueryCriteria criteria) {
        return tbShopUserMapper.toDto(tbShopUserRepository.findAll((root, criteriaQuery, criteriaBuilder) -> QueryHelp.getPredicate(root, criteria, criteriaBuilder)));
    }

    @Override
    @Transactional
    public TbShopUserDto findById(Integer id) {
        TbShopUser tbShopUser = tbShopUserRepository.findById(id).orElseGet(TbShopUser::new);
        ValidationUtil.isNull(tbShopUser.getId(), "TbShopUser", "id", id);
        return tbShopUserMapper.toDto(tbShopUser);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public TbShopUserDto create(TbShopUser resources) {
        return tbShopUserMapper.toDto(tbShopUserRepository.save(resources));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(TbShopUser resources) {
        TbShopUser tbShopUser = tbShopUserRepository.findById(resources.getId()).orElseGet(TbShopUser::new);
        ValidationUtil.isNull(tbShopUser.getId(), "TbShopUser", "id", resources.getId());
        tbShopUser.copy(resources);
        tbShopUserRepository.save(tbShopUser);
    }

    @Override
    public void deleteAll(Integer[] ids) {
        for (Integer id : ids) {
            tbShopUserRepository.deleteById(id);
        }
    }

    @Override
    public void download(List<TbShopUserDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (TbShopUserDto tbShopUser : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("钱包余额", tbShopUser.getAmount());
            map.put("授权金额", tbShopUser.getCreditAmount());
            map.put("消费累计", tbShopUser.getConsumeAmount());
            map.put("消费数量累计", tbShopUser.getConsumeNumber());
            map.put("等级积分", tbShopUser.getLevelConsume());
            map.put("0-不可使用 1可使用", tbShopUser.getStatus());
            map.put("代理Id", tbShopUser.getMerchantId());
            map.put("店铺Id", tbShopUser.getShopId());
            map.put("用户Id", tbShopUser.getUserId());
            map.put("上级Id", tbShopUser.getParentId());
            map.put("上级的层级", tbShopUser.getParentLevel());
            map.put("真实名字", tbShopUser.getName());
            map.put(" headImg", tbShopUser.getHeadImg());
            map.put("性别", tbShopUser.getSex());
            map.put("生日", tbShopUser.getBirthDay());
            map.put("联系电话", tbShopUser.getTelephone());
            map.put("是否会员，", tbShopUser.getIsVip());
            map.put("会员编号", tbShopUser.getCode());
            map.put("是否通过关注而成为会员的，此字段固定后不改", tbShopUser.getIsAttention());
            map.put("关注时间", tbShopUser.getAttentionAt());
            map.put("是否股东（分销商）", tbShopUser.getIsShareholder());
            map.put("层级1-顶级 2-次级 3最低", tbShopUser.getLevel());
            map.put("分销类型 auto-自动获取 set手动设置 charge充值", tbShopUser.getDistributeType());
            map.put("排序", tbShopUser.getSort());
            map.put(" createdAt", tbShopUser.getCreatedAt());
            map.put(" updatedAt", tbShopUser.getUpdatedAt());
            map.put("小程序openId", tbShopUser.getMiniOpenId());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public IPage<TbShopRechargeRespDto> rechargeList(TbShopRechargeListDto criteria, Pageable pageable) {
        if (criteria.getStartTime() == null) {
            criteria.setStartTime(DateUtil.parseDate("2024-01-01 00:00:00"));
        }
        if (criteria.getEndTime() == null) {
            criteria.setEndTime(DateUtil.date(Instant.now()));
        }

        return shopUserMapper.queryRechargeList(criteria,
                new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(pageable == null ? 0 : pageable.getPageNumber(), pageable == null ? 1000000 : pageable.getPageSize()));
    }

    @Override
    public void rechargeListDownload(HttpServletResponse response, TbShopRechargeListDto criteria) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        IPage<TbShopRechargeRespDto> page = rechargeList(criteria, null);
        for (TbShopRechargeRespDto tbShopRechargeRespDto : page.getRecords()) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("id", tbShopRechargeRespDto.getId());
            map.put("门店", tbShopRechargeRespDto.getShopName());
            map.put("用户手机号", tbShopRechargeRespDto.getUserPhone());
            map.put("用户名", tbShopRechargeRespDto.getUserName());
            map.put("充值金额", tbShopRechargeRespDto.getRechargeAmount());
            map.put("充值类型", tbShopRechargeRespDto.getRechargeType());
            map.put("充值时间", tbShopRechargeRespDto.getRechargeTime());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public void modfiyAccount(Map<String, Object> map) {
        if (ObjectUtil.isNull(map) || ObjectUtil.isEmpty(map) || !map.containsKey("id") || !map.containsKey("type") || !map.containsKey("amount")
                || ObjectUtil.isEmpty(map.get("id")) || ObjectUtil.isNull(map.get("id")) || ObjectUtil.isNull(map.get("type")) || ObjectUtil.isEmpty(map.get("type"))
                || ObjectUtil.isEmpty(map.get("amount")) || ObjectUtil.isNull(map.get("amount")) || !map.containsKey("operationType") || ObjectUtil.isEmpty(map.get("operationType")) || ObjectUtil.isNull(map.get("operationType"))

        ) {
            throw new BadRequestException("参数错误");

        }

        String regex = "^(([1-9][0-9]*)|(([0]\\.\\d{1,2}|[1-9][0-9]*\\.\\d{1,2})))$";
        if (!map.get("amount").toString().matches(regex)) {
            throw new BadRequestException("请输入正确的数字");
        }


        TbShopUser tbShopUser = tbShopUserRepository.getById(Integer.valueOf(map.get("id") + ""));
        if (ObjectUtil.isNull(tbShopUser)) {
            throw new BadRequestException("不存在的会员信息");
        }
        String operationType = map.get("operationType").toString();

        BigDecimal amount = new BigDecimal(map.get("amount").toString());
        if ("out".equals(operationType)) {
            if (amount.compareTo(tbShopUser.getAmount()) > 0) {
                throw new BadRequestException("账户余额不足，请输入正确的金额");
            }
        }


        String type = map.get("type").toString();
        TbShopUserFlow flow = new TbShopUserFlow();

        if ("in".equals(operationType)) {
            flow.setType("+");
            flow.setBizName("inMoney".equals(type) ? "充值" : "消费退款");
            flow.setBizCode("inMoney".equals(type) ? "inMoneyIn" : "consumeIn");
            tbShopUser.setAmount(tbShopUser.getAmount().add(amount));
        } else if ("out".equals(operationType)) {
            flow.setBizName("inMoneyOut".equals(type) ? "充值退款" : "消费");
            flow.setBizCode("inMoneyOut".equals(type) ? "inMoneyOut" : "consumeOut");
            flow.setType("-");
            tbShopUser.setAmount(tbShopUser.getAmount().subtract(amount));
        } else {
            throw new BadRequestException("错误的请求类型");
        }

        tbShopUser.setUpdatedAt(System.currentTimeMillis());
        tbShopUserRepository.save(tbShopUser);


        flow.setShopUserId(tbShopUser.getId());
        flow.setAmount(amount);
        flow.setBalance(tbShopUser.getAmount());
        flow.setCreateTime(new Timestamp(System.currentTimeMillis()));

        tbShopUserFlowMapper.insert(flow);


    }

}
