import { CrudHttpError } from "@open-mercato/shared/lib/crud/errors";
import { SalesTaxRate } from "../data/entities.js";
class DefaultTaxCalculationService {
  constructor(em, eventBus) {
    this.em = em;
    this.eventBus = eventBus;
  }
  async calculateUnitAmounts(input) {
    let workingInput = { ...input };
    let resolved;
    if (this.eventBus) {
      await this.eventBus.emitEvent("sales.tax.calculate.before", {
        input: workingInput,
        setInput(next) {
          if (!next) return;
          workingInput = { ...workingInput, ...next };
        },
        setResult(next) {
          if (next) resolved = next;
        }
      });
      if (resolved) return resolved;
    }
    resolved = await this.performCalculation(workingInput);
    if (this.eventBus) {
      await this.eventBus.emitEvent("sales.tax.calculate.after", {
        input: workingInput,
        result: resolved,
        setResult(next) {
          if (next) resolved = next;
        }
      });
    }
    return resolved;
  }
  async performCalculation(input) {
    const amount = this.normalizeAmount(input.amount);
    const mode = input.mode === "gross" ? "gross" : input.mode === "net" ? "net" : null;
    if (!mode) {
      throw new CrudHttpError(400, { error: "Unsupported tax calculation mode." });
    }
    const { rate, hasValue } = await this.resolveRate(input);
    const fraction = hasValue ? rate / 100 : 0;
    let netAmount;
    let grossAmount;
    if (mode === "net") {
      netAmount = amount;
      grossAmount = amount * (1 + fraction);
    } else {
      grossAmount = amount;
      netAmount = fraction > 0 ? amount / (1 + fraction) : amount;
    }
    const taxAmount = grossAmount - netAmount;
    return {
      netAmount: roundAmount(netAmount),
      grossAmount: roundAmount(grossAmount),
      taxAmount: roundAmount(taxAmount),
      taxRate: hasValue ? roundRate(rate) : null
    };
  }
  async resolveRate(input) {
    if (input.taxRateId) {
      const rate = await this.em.findOne(
        SalesTaxRate,
        {
          id: input.taxRateId,
          organizationId: input.organizationId,
          tenantId: input.tenantId,
          deletedAt: null
        },
        { fields: ["rate", "organizationId", "tenantId"] }
      );
      if (!rate) {
        throw new CrudHttpError(400, { error: "Tax class not found for this organization." });
      }
      return { rate: this.normalizeRate(rate.rate), hasValue: true };
    }
    if (input.taxRate !== void 0 && input.taxRate !== null) {
      return { rate: this.normalizeRate(input.taxRate), hasValue: true };
    }
    return { rate: 0, hasValue: false };
  }
  normalizeAmount(value) {
    if (!Number.isFinite(value) || value < 0) {
      throw new CrudHttpError(400, { error: "Amount must be zero or greater." });
    }
    return value;
  }
  normalizeRate(value) {
    const numeric = typeof value === "string" ? Number(value) : typeof value === "number" ? value : Number.NaN;
    if (!Number.isFinite(numeric) || numeric < 0) return 0;
    return numeric;
  }
}
function roundAmount(value, precision = 4) {
  const factor = 10 ** precision;
  return Math.round(value * factor) / factor;
}
function roundRate(value, precision = 4) {
  return roundAmount(value, precision);
}
export {
  DefaultTaxCalculationService
};
//# sourceMappingURL=taxCalculationService.js.map
