package cn.iocoder.yudao.module.system.service.reservation;

import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.system.controller.admin.reservation.vo.ReservationBedRespVO;
import cn.iocoder.yudao.module.system.controller.admin.reservation.vo.ReservationPayVO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.BuildBedDO;
import cn.iocoder.yudao.module.system.dal.dataobject.reservation.ReservationBedDO;
import cn.iocoder.yudao.module.system.dal.dataobject.reservation.ReservationDepositDO;
import cn.iocoder.yudao.module.system.dal.dataobject.reservation.ReservationDepositPayDO;
import cn.iocoder.yudao.module.system.dal.dataobject.reservation.ReservationDepositRefundDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.BuildBedMapper;
import cn.iocoder.yudao.module.system.dal.mysql.reservation.ReservationBedMapper;
import cn.iocoder.yudao.module.system.dal.mysql.reservation.ReservationDepositMapper;
import cn.iocoder.yudao.module.system.dal.mysql.reservation.ReservationDepositPayMapper;
import cn.iocoder.yudao.module.system.dal.mysql.reservation.ReservationDepositRefundMapper;
import cn.iocoder.yudao.module.system.service.biz.BuildService;
import org.jacoco.agent.rt.internal_4a7f17c.core.internal.flow.IFrame;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

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

/**
 * 预约床位押金 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
public class ReservationDepositServiceImpl implements ReservationDepositService {

    @Resource
    private ReservationBedMapper reservationBedMapper;
    @Resource
    private ReservationDepositMapper reservationDepositMapper;
    @Resource
    private ReservationDepositPayMapper reservationDepositPayMapper;
    @Resource
    private BuildService buildService;
    @Resource
    private BuildBedMapper buildBedMapper;
    @Resource
    private ReservationDepositRefundMapper reservationDepositRefundMapper;


    @Override
    @Transactional
    public void payFees(ReservationPayVO reservationPayVO) {
        ReservationDepositDO reservationDepositDO = reservationDepositMapper.selectOne(new LambdaQueryWrapperX<ReservationDepositDO>()
                .eq(ReservationDepositDO::getReservationId, reservationPayVO.getReservationId()));
        reservationDepositDO = reservationDepositDO == null ? new ReservationDepositDO() : reservationDepositDO;
        BeanUtils.copyProperties(reservationPayVO,reservationDepositDO);
        //修改状态
        ReservationBedDO reservationBedDO = reservationBedMapper.selectById(reservationPayVO.getReservationId());
        reservationBedDO.setStatus(2);
        reservationBedDO.setPayStatus(1);
        reservationBedDO.setPayTime(new Date());
        reservationBedDO.setPayeeName(SecurityFrameworkUtils.getLoginUserNickname());
        reservationBedMapper.updateById(reservationBedDO);

        //修改床位状态
        BuildBedDO bedDO = buildBedMapper.selectById(reservationBedDO.getBedId());
        if (bedDO != null) {
            bedDO.setStatus(2); //预订状态
            buildBedMapper.updateById(bedDO);

            //将其他预约该床位的数据更改预约失败状态
            List<ReservationBedDO> reservationBedList = reservationBedMapper.selectList(new LambdaQueryWrapperX<ReservationBedDO>()
                    .eq(ReservationBedDO::getBedId, reservationBedDO.getBedId())
                    .eq(ReservationBedDO::getStatus, 0));

            for (ReservationBedDO reservationBed : reservationBedList) {
                reservationBed.setStatus(3);
                reservationBedMapper.updateById(reservationBed);
            }
        }

        List<ReservationDepositPayDO> payInfo = reservationPayVO.getPayInfo();
        if(reservationDepositDO.getId() == null){
            reservationDepositMapper.insert(reservationDepositDO);
        }else {
            reservationDepositMapper.updateById(reservationDepositDO);
            reservationDepositPayMapper.delete(ReservationDepositPayDO::getReservationId,reservationDepositDO.getReservationId());
        }
        for (ReservationDepositPayDO reservationDepositPayDO : payInfo) {
            reservationDepositPayDO.setPayeeName(SecurityFrameworkUtils.getLoginUserNickname());
            reservationDepositPayDO.setPayStatus(1);
            reservationDepositPayDO.setPayTime(new Date());
            reservationDepositPayMapper.insert(reservationDepositPayDO);
        }
    }

    @Override
    public ReservationBedRespVO getReservationDetail(Long reservationId) {
        ReservationBedDO reservationBedDO = reservationBedMapper.selectById(reservationId);
        ReservationBedRespVO respVO = new ReservationBedRespVO();
        BeanUtils.copyProperties(reservationBedDO, respVO);
        respVO.setFullBedName(buildService.getFullBedNameByBedId(reservationBedDO.getBedId()));
        //查询支付信息
        List<ReservationDepositPayDO> payInfo = reservationDepositPayMapper.selectList(new LambdaQueryWrapperX<ReservationDepositPayDO>()
                .eq(ReservationDepositPayDO::getReservationId, reservationId));
        respVO.setPayInfo(payInfo);
        ReservationDepositDO reservationDepositDO = reservationDepositMapper.selectOne(new LambdaQueryWrapperX<ReservationDepositDO>()
                .eq(ReservationDepositDO::getReservationId, reservationId));
        if (reservationDepositDO != null){
            respVO.setDepositAmount(reservationDepositDO.getDepositAmount());
        }
        List<ReservationDepositRefundDO> refundInfo = reservationDepositRefundMapper.selectList(new LambdaQueryWrapperX<ReservationDepositRefundDO>()
                .eq(ReservationDepositRefundDO::getReservationId, reservationId));
        respVO.setRefundInfo(refundInfo);
        return respVO;
    }

    @Override
    public void refund(Long reservationId) {
        ReservationDepositDO reservationDepositDO = reservationDepositMapper.selectOne(new LambdaQueryWrapperX<ReservationDepositDO>()
                .eq(ReservationDepositDO::getReservationId, reservationId));

        BigDecimal depositAmount = reservationDepositDO.getDepositAmount();
        reservationDepositDO.setDepositAmount(BigDecimal.ZERO); //退全部
        reservationDepositMapper.updateById(reservationDepositDO);

        //修改状态
        ReservationBedDO reservationBedDO = reservationBedMapper.selectById(reservationId);
        reservationBedDO.setStatus(4);  //关闭
        reservationBedDO.setPayStatus(2); //已退费
        reservationBedMapper.updateById(reservationBedDO);

        BuildBedDO bedDO = buildBedMapper.selectById(reservationBedDO.getBedId());
        if (bedDO != null) {
            //释放床位
            bedDO.setStatus(0);
            buildBedMapper.updateById(bedDO);
        }

        //todo 生成退费记录
        ReservationDepositRefundDO refundDO = new ReservationDepositRefundDO();
        refundDO.setRefundAmount(depositAmount);
        refundDO.setReservationId(reservationId);
        refundDO.setRefundTime(new Date());
        refundDO.setCreatedTime(new Date());
        refundDO.setCreatedBy(SecurityFrameworkUtils.getLoginUserNickname());
        reservationDepositRefundMapper.insert(refundDO);
    }

    @Override
    public Long getBedIdByIdCard(String idCard) {
        // 获取已缴费的预约床位
        ReservationBedDO reservationBedDO = reservationBedMapper.selectOne(new LambdaQueryWrapperX<ReservationBedDO>()
                .eq(ReservationBedDO::getIdNumber, idCard)
                .eq(ReservationBedDO::getTenantId, TenantContextHolder.getTenantId())
                .eq(ReservationBedDO::getStatus, 2)
                .select(ReservationBedDO::getBedId));
        return reservationBedDO == null ? null : reservationBedDO.getBedId();
    }
}