package com.yuchen.saas.park.service.service.property;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.thinkunion.park.service.common.utils.AmtUtil;
import com.yuchen.saas.park.api.dto.property.PropertyBillingSettingsSaveDto;
import com.yuchen.saas.park.api.entity.property.PropertyBillingSettings;
import com.yuchen.saas.park.api.enums.property.YesOrNoEnum;
import com.yuchen.saas.park.service.constant.PropertyCacheConstant;
import com.yuchen.saas.park.service.mapper.property.PropertyBillingSettingsMapper;
import lombok.extern.slf4j.Slf4j;
import org.nest.springwrap.core.log.exception.ServiceException;
import org.nest.springwrap.core.tool.utils.BeanUtil;
import org.nest.springwrap.core.tool.utils.Func;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;

/**
 * 账单设置
 */
@Slf4j
@Service
public class PropertyBillingSettingsService extends ServiceImpl<PropertyBillingSettingsMapper, PropertyBillingSettings> {
    @Resource
    private BeanFactory beanFactory;

    private PropertyBillingSettingsService thisService() {
        return beanFactory.getBean(PropertyBillingSettingsService.class);
    }

    /**
     * 保存
     * @param dto
     */
    public void saveBillingSettings(PropertyBillingSettingsSaveDto dto) {
        this.verifySave(dto);
        PropertyBillingSettings po = this.assembleSaveDto(dto);
        this.saveOrUpdate(po);
    }

    /**
     * 保存前参数校验
     * @param dto
     */
    private void verifySave(PropertyBillingSettingsSaveDto dto) {
        if (Func.isEmpty(dto.getId())) {
            LambdaQueryWrapper<PropertyBillingSettings> qw = new LambdaQueryWrapper<>();
            qw.eq(PropertyBillingSettings::getParkId,dto.getParkId());
            if (this.count(qw) > 0) {
                throw new ServiceException("该园区已设置账单参数");
            }
        }

        if (Func.isNotEmpty(dto.getAutoBillStatus())
            && dto.getAutoBillStatus() == YesOrNoEnum.YES.getValue()
            && Func.isEmpty(dto.getAutoFirstDay())) {
            throw new ServiceException("第一次自动生成账单日期不能为空");
        }

        if (Func.isNotEmpty(dto.getAutoSeductionStatus())
            && dto.getAutoSeductionStatus() == YesOrNoEnum.YES.getValue()
            && Func.isEmpty(dto.getAutoSeductionDay())) {
            throw new ServiceException("自动冲抵账单日期参数不能为空");
        }
    }

    /**
     * 保存参数组装
     * @param dto
     * @return
     */
    private PropertyBillingSettings assembleSaveDto(PropertyBillingSettingsSaveDto dto) {
        PropertyBillingSettings po;
        if (Func.isEmpty(dto.getId())) {
            po = BeanUtil.copyProperties(dto,PropertyBillingSettings.class);
            po.setCreateTime(new Date());
        } else {
            po = this.getById(dto.getId());
            BeanUtil.copyProperties(dto,po);
        }

        if (Func.isEmpty(dto.getAutoBillStatus()) ||
                dto.getAutoBillStatus() == YesOrNoEnum.NO.getValue()) {
            //关闭时，数据清空
            po.setAutoBillStatus(YesOrNoEnum.NO.getValue());
            po.setAutoFirstDay(null);
            po.setAutoSecondDay(null);
        }

        if (Func.isEmpty(dto.getAutoSeductionStatus()) ||
                dto.getAutoSeductionStatus() == YesOrNoEnum.NO.getValue()) {
            po.setAutoSeductionStatus(YesOrNoEnum.NO.getValue());
            po.setAutoSeductionDay(null);
        }

        return po;
    }


    /**
     * 获取账单设置，如果未设置，返回默认设置值
     * @param parkId
     * @return
     */
    @Cacheable(cacheNames = PropertyCacheConstant.BILL_SETTINGS_CACHE + "#300", key = "#parkId")
    public PropertyBillingSettings getBillingSettings(Long parkId) {
        LambdaQueryWrapper<PropertyBillingSettings> qw = new LambdaQueryWrapper<>();
        qw.eq(PropertyBillingSettings::getParkId,parkId);
        PropertyBillingSettings po = this.getOne(qw);
        if (po == null) {
            po = new PropertyBillingSettings();
            po.setParkId(parkId);
            po.setTradeOffType(1);
            po.setAmountDigitsType(2);
            po.setMeterDigitsType(2);
            po.setZeroBillStatus(0);
            po.setAutoBillStatus(0);
            po.setAutoFirstDay(1);
            po.setAutoSecondDay(2);
            po.setAutoSeductionStatus(0);
            po.setAutoSeductionDay(1);
        }
        return po;
    }

    /**
     * 金额元; 按账单小数设置后转换
     * @param parkId
     * @param amtYuan
     * @return
     */
    public BigDecimal getBillAmtByYuan(long parkId,BigDecimal amtYuan) {
        if (amtYuan == null) {
            return null;
        }
        PropertyBillingSettings settings = thisService().getBillingSettings(parkId);
        if (settings.getTradeOffType() == 1) { // 1-四舍五入，2-直接舍掉
            amtYuan = amtYuan.setScale(settings.getAmountDigitsType(), RoundingMode.HALF_UP);
        } else {
            amtYuan = amtYuan.setScale(0, RoundingMode.FLOOR);
        }
        return amtYuan;
    }

    /**
     * 金额分; 按账单小数设置后转换
     * @param parkId
     * @param amtFen
     * @return
     */
    public long getBillAmtByFen(long parkId,long amtFen) {
        BigDecimal amt = this.getBillAmtByYuan(parkId,AmtUtil.fenToYuan(amtFen));
        return AmtUtil.yuanToFen(amt);
    }



}
