package cn.iocoder.yudao.module.member.service.card;

import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.member.controller.admin.card.vo.CardPageReqVO;
import cn.iocoder.yudao.module.member.controller.admin.card.vo.CardSaveReqVO;
import cn.iocoder.yudao.module.member.controller.app.card.vo.AppCardMonthVO;
import cn.iocoder.yudao.module.member.controller.app.card.vo.AppCardPageReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.card.CardDO;
import cn.iocoder.yudao.module.member.dal.mysql.card.CardMapper;
import cn.iocoder.yudao.module.member.enums.CostTypeEnum;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.member.util.MemberConstants;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.List;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.CARD_NOT_EXISTS;

/**
 * 余额变动明细 Service 实现类
 *
 * @author 开发账号
 */
@Service
@Validated
public class CardServiceImpl implements CardService {

    @Resource
    private CardMapper cardMapper;
    @Resource
    private MemberUserService userService;

    @Override
    public Long createCard(CardSaveReqVO createReqVO) {
        // 插入
        CardDO card = BeanUtils.toBean(createReqVO, CardDO.class);
        cardMapper.insert(card);
        // 返回
        return card.getId();
    }

    @Override
    public void updateCard(CardSaveReqVO updateReqVO) {
        // 校验存在
        validateCardExists(updateReqVO.getId());
        // 更新
        CardDO updateObj = BeanUtils.toBean(updateReqVO, CardDO.class);
        cardMapper.updateById(updateObj);
    }

    @Override
    public void deleteCard(Long id) {
        // 校验存在
        validateCardExists(id);
        // 删除
        cardMapper.deleteById(id);
    }

    private void validateCardExists(Long id) {
        if (cardMapper.selectById(id) == null) {
            throw exception(CARD_NOT_EXISTS);
        }
    }

    @Override
    public CardDO getCard(Long id) {
        return cardMapper.selectById(id);
    }

    @Override
    public PageResult<CardDO> getCardPage(CardPageReqVO pageReqVO) {
        return cardMapper.selectPage(pageReqVO);
    }

    @Override
    public PageResult<CardDO> getCardPage(AppCardPageReqVO pageReqVO) {
        return cardMapper.selectPage(pageReqVO);
    }


    @Override
    public Boolean recharge(BigDecimal money, String flag) {
        //获取最新余额
        CardDO lastCardDO = getLastCardDO();
        CardDO cardDO = new CardDO();
        cardDO.setUserId(SecurityFrameworkUtils.getLoginUserId());
        cardDO.setFlag(flag);
        cardDO.setChangeMoney(money);
        cardDO.setType(CostTypeEnum.WX_PAY.getCode());
        BigDecimal oldMoney = BigDecimal.ZERO;
        if (ObjectUtil.isNotEmpty(lastCardDO) && lastCardDO.getMoney() != null) {
            oldMoney = lastCardDO.getMoney();
        }
        if (CardDO.ADD.equals(flag)) {
            cardDO.setMoney(oldMoney.add(money).setScale(2, BigDecimal.ROUND_HALF_UP));
        } else {
            cardDO.setMoney(oldMoney.subtract(money).setScale(2, BigDecimal.ROUND_HALF_UP));
        }
        return cardMapper.insert(cardDO) > 0;
    }

    @Override
    public BigDecimal getMoney() {
        CardDO lastCardDO = getLastCardDO();
        if (ObjectUtil.isEmpty(lastCardDO) || lastCardDO.getMoney() == null) {
            return BigDecimal.ZERO;
        }
        return lastCardDO.getMoney();
    }

    @Override
    public BigDecimal getMoneyByUserId(Long userId) {
        CardDO lastCardDO = cardMapper.selectOne(Wrappers.<CardDO>lambdaQuery().eq(CardDO::getUserId, userId)
                .orderByDesc(CardDO::getCreateTime).last(MemberConstants.LIMIT_ONE));
        if (lastCardDO == null || lastCardDO.getMoney() == null) {
            return BigDecimal.ZERO;
        }
        return lastCardDO.getMoney();
    }

    /**
     * 获取当前用户最新余额明细
     *
     * @return
     */
    public CardDO getLastCardDO() {
        CardDO lastCardDO = cardMapper.selectOne(Wrappers.<CardDO>lambdaQuery().eq(CardDO::getUserId, SecurityFrameworkUtils.getLoginUserId())
                .orderByDesc(CardDO::getCreateTime).last(MemberConstants.LIMIT_ONE));
        return lastCardDO;
    }

    @Override
    public void insertBatch(List<CardDO> list) {
        cardMapper.insertBatch(list);
    }

    @Override
    public AppCardMonthVO getMonthMoney(Long userId, String flag, String time) {

        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(MemberConstants.TIME_FORMAT);
        LocalDate parse = LocalDate.parse(time, dateFormatter);

        // 获取指定日期所在月份的第一天
        LocalDate firstDayOfMonth = parse.withDayOfMonth(1);

        // 获取指定日期所在月份的最后一天
        YearMonth yearMonth = YearMonth.from(parse);
        LocalDate lastDayOfMonth = yearMonth.atEndOfMonth();

        // 获取所在月份的第一天的开始时间
        LocalDateTime firstDayOfMonthStart = firstDayOfMonth.atStartOfDay();

        // 获取所在月份的最后一天的结束时间
        LocalDateTime lastDayOfMonthEnd = lastDayOfMonth.atTime(LocalTime.MAX);
        AppCardMonthVO appCardMonthVO = cardMapper.selectMonth(userId, flag, firstDayOfMonthStart, lastDayOfMonthEnd);

        return appCardMonthVO;


    }
}