package com.yhy.module.core.dal.dataobject.quota;

import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.yhy.module.core.dal.typehandler.PostgreSQLJsonbTypeHandler;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.math.BigDecimal;
import java.util.Map;

/**
 * 定额子目工料机组成 DO
 * 
 * 对应表 yhy_quota_resource
 * 
 * 定义定额子目包含哪些工料机资源及其用量
 * 
 * @author yhy
 */
@TableName(value = "yhy_quota_resource", autoResultMap = true)
@KeySequence("yhy_quota_resource_id_seq")
@Data
@EqualsAndHashCode(callSuper = true)
public class QuotaResourceDO extends TenantBaseDO {

    /**
     * 主键
     */
    @TableId
    private Long id;

    /**
     * 定额子目ID（关联 yhy_quota_item）
     */
    private Long quotaItemId;

    /**
     * 资源项ID（关联 yhy_resource_item）
     */
    private Long resourceItemId;

    /**
     * 定额消耗量/用量
     * 
     * 例如：1m³混凝土需要 350kg 水泥，则 dosage = 350
     */
    private BigDecimal dosage;

    /**
     * 扩展属性（JSONB）
     * 
     * 可存储：
     * - loss_rate: 损耗率（如 0.02 表示 2%）
     * - price: 价格快照（套用定额时记录）
     * - resource_code: 资源编码快照
     * - resource_name: 资源名称快照
     * - resource_unit: 资源单位快照
     * - 其他自定义字段
     */
    @TableField(typeHandler = PostgreSQLJsonbTypeHandler.class)
    private Map<String, Object> attributes;

    // ========== 便捷方法 ==========

    /**
     * 获取损耗率
     */
    public BigDecimal getLossRate() {
        if (attributes == null) return BigDecimal.ZERO;
        Object value = attributes.get("loss_rate");
        if (value instanceof Number) {
            return new BigDecimal(value.toString());
        }
        return BigDecimal.ZERO;
    }

    /**
     * 设置损耗率
     */
    public void setLossRate(BigDecimal lossRate) {
        if (attributes == null) {
            attributes = new java.util.HashMap<>();
        }
        attributes.put("loss_rate", lossRate);
    }

    /**
     * 获取价格快照
     */
    public BigDecimal getPrice() {
        if (attributes == null) return null;
        Object value = attributes.get("price");
        if (value instanceof Number) {
            return new BigDecimal(value.toString());
        }
        return null;
    }

    /**
     * 设置价格快照
     */
    public void setPrice(BigDecimal price) {
        if (attributes == null) {
            attributes = new java.util.HashMap<>();
        }
        attributes.put("price", price);
    }

    /**
     * 获取资源编码快照
     */
    public String getResourceCode() {
        return attributes != null ? (String) attributes.get("resource_code") : null;
    }

    /**
     * 设置资源编码快照
     */
    public void setResourceCode(String resourceCode) {
        if (attributes == null) {
            attributes = new java.util.HashMap<>();
        }
        attributes.put("resource_code", resourceCode);
    }

    /**
     * 获取资源名称快照
     */
    public String getResourceName() {
        return attributes != null ? (String) attributes.get("resource_name") : null;
    }

    /**
     * 设置资源名称快照
     */
    public void setResourceName(String resourceName) {
        if (attributes == null) {
            attributes = new java.util.HashMap<>();
        }
        attributes.put("resource_name", resourceName);
    }

    /**
     * 获取资源单位快照
     */
    public String getResourceUnit() {
        return attributes != null ? (String) attributes.get("resource_unit") : null;
    }

    /**
     * 设置资源单位快照
     */
    public void setResourceUnit(String resourceUnit) {
        if (attributes == null) {
            attributes = new java.util.HashMap<>();
        }
        attributes.put("resource_unit", resourceUnit);
    }

    /**
     * 计算实际消耗量（含损耗）
     * 
     * actual_dosage = dosage * (1 + loss_rate)
     */
    public BigDecimal getActualDosage() {
        BigDecimal lossRate = getLossRate();
        return dosage.multiply(BigDecimal.ONE.add(lossRate));
    }

    /**
     * 计算金额
     * 
     * amount = actual_dosage * price
     */
    public BigDecimal getAmount() {
        BigDecimal price = getPrice();
        if (price == null) return null;
        return getActualDosage().multiply(price);
    }
}
