package com.yhy.module.core.service.workbench;

import java.math.BigDecimal;

/**
 * 定额工程量公式计算服务
 * 
 * @author yhy
 */
public interface QuotaQtyFormulaService {

    /**
     * 验证公式合法性
     * 
     * @param formula 公式字符串（如 QDL*2）
     * @return 验证结果
     */
    FormulaValidationResult validateFormula(String formula);

    /**
     * 计算定额工程量
     * 
     * @param formula 公式字符串（如 QDL*2）
     * @param qdlValue 清单工程量值
     * @return 计算结果（四舍五入保留3位小数）
     */
    BigDecimal calculateQuotaQty(String formula, BigDecimal qdlValue);

    /**
     * 计算定额工程量（带单位换算）
     * 
     * @param formula 公式字符串（如 QDL*2）
     * @param qdlValue 清单工程量值
     * @param quotaUnit 定额单位（如"100m"、"m"、"件"）
     * @return 计算结果（四舍五入保留3位小数）
     * 
     * 单位换算规则：
     * - 如果单位以数字开头（如"100m"），则提取数字作为换算系数，QDL = 清单工程量 / 系数
     * - 如果单位是纯字符串（如"m"、"件"），则不换算，QDL = 清单工程量
     */
    BigDecimal calculateQuotaQty(String formula, BigDecimal qdlValue, String quotaUnit);

    /**
     * 从单位字符串中解析换算系数
     * 
     * @param unit 单位字符串（如"100m"、"m"、"件"）
     * @return 换算系数（如100、1）
     */
    BigDecimal parseUnitFactor(String unit);

    /**
     * 根据定额ID重新计算工程量
     * 
     * @param quotaDivisionId 定额节点ID
     * @return 计算后的工程量
     */
    BigDecimal recalculateQuotaQty(Long quotaDivisionId);

    /**
     * 清单工程量变化时，重新计算所有子定额的工程量
     * 
     * @param boqDivisionId 清单节点ID
     */
    void recalculateChildQuotaQty(Long boqDivisionId);

    /**
     * 公式验证结果
     */
    class FormulaValidationResult {
        private boolean valid;
        private String error;
        private BigDecimal testResult;

        public static FormulaValidationResult success(BigDecimal testResult) {
            FormulaValidationResult result = new FormulaValidationResult();
            result.valid = true;
            result.testResult = testResult;
            return result;
        }

        public static FormulaValidationResult failure(String error) {
            FormulaValidationResult result = new FormulaValidationResult();
            result.valid = false;
            result.error = error;
            return result;
        }

        public boolean isValid() {
            return valid;
        }

        public String getError() {
            return error;
        }

        public BigDecimal getTestResult() {
            return testResult;
        }
    }
}
