/**
 * Pure commercial-terms calculation engine.
 *
 * Applies contingency, discount, and payment milestone validation
 * to base cost/price totals from demand lines.
 */

import type { CommercialTerms, CommercialTermsSummary, PaymentMilestone } from "@capakraken/shared";

export interface CommercialTermsInput {
  baseCostCents: number;
  basePriceCents: number;
  terms: CommercialTerms;
}

/**
 * Compute adjusted totals after applying contingency and discount.
 *
 * Contingency is added to cost (risk buffer on cost side).
 * Discount is subtracted from price (reduction on sell side).
 *
 * adjustedCost  = baseCost * (1 + contingency%)
 * adjustedPrice = basePrice * (1 - discount%)
 * margin        = adjustedPrice - adjustedCost
 */
export function computeCommercialTermsSummary(
  input: CommercialTermsInput,
): CommercialTermsSummary {
  const { baseCostCents, basePriceCents, terms } = input;

  const contingencyFactor = terms.contingencyPercent / 100;
  const discountFactor = terms.discountPercent / 100;

  const contingencyCents = Math.round(baseCostCents * contingencyFactor);
  const discountCents = Math.round(basePriceCents * discountFactor);

  const adjustedCostCents = baseCostCents + contingencyCents;
  const adjustedPriceCents = basePriceCents - discountCents;
  const adjustedMarginCents = adjustedPriceCents - adjustedCostCents;
  const adjustedMarginPercent =
    adjustedPriceCents > 0
      ? (adjustedMarginCents / adjustedPriceCents) * 100
      : 0;

  return {
    baseCostCents,
    basePriceCents,
    contingencyCents,
    discountCents,
    adjustedCostCents,
    adjustedPriceCents,
    adjustedMarginCents,
    adjustedMarginPercent,
  };
}

/**
 * Validate that payment milestones sum to 100%.
 * Returns list of validation warnings (empty = valid).
 */
export function validatePaymentMilestones(
  milestones: PaymentMilestone[],
): string[] {
  const warnings: string[] = [];

  if (milestones.length === 0) return warnings;

  const totalPercent = milestones.reduce((sum, m) => sum + m.percent, 0);

  if (Math.abs(totalPercent - 100) > 0.01) {
    warnings.push(
      `Payment milestones sum to ${totalPercent.toFixed(1)}%, expected 100%`,
    );
  }

  for (let i = 0; i < milestones.length; i++) {
    const m = milestones[i]!;
    if (m.percent <= 0) {
      warnings.push(`Milestone "${m.label}" has 0% or negative allocation`);
    }
    if (!m.label.trim()) {
      warnings.push(`Milestone at position ${i + 1} has empty label`);
    }
  }

  // Check chronological order when dates are provided
  const datedMilestones = milestones.filter(
    (m): m is PaymentMilestone & { dueDate: string } =>
      m.dueDate != null && m.dueDate !== "",
  );
  for (let i = 1; i < datedMilestones.length; i++) {
    if (datedMilestones[i]!.dueDate < datedMilestones[i - 1]!.dueDate) {
      warnings.push(
        `Milestone "${datedMilestones[i]!.label}" has an earlier date than "${datedMilestones[i - 1]!.label}"`,
      );
    }
  }

  return warnings;
}

/**
 * Compute per-milestone payment amounts from adjusted price.
 */
export function computeMilestoneAmounts(
  adjustedPriceCents: number,
  milestones: PaymentMilestone[],
): Array<{ label: string; percent: number; amountCents: number; dueDate?: string | null }> {
  return milestones.map((m) => ({
    label: m.label,
    percent: m.percent,
    amountCents: Math.round(adjustedPriceCents * (m.percent / 100)),
    ...(m.dueDate !== undefined ? { dueDate: m.dueDate } : {}),
  }));
}

/**
 * Default commercial terms for a new estimate.
 */
export function defaultCommercialTerms(): CommercialTerms {
  return {
    pricingModel: "fixed_price",
    contingencyPercent: 0,
    discountPercent: 0,
    paymentTermDays: 30,
    paymentMilestones: [],
    warrantyMonths: 0,
  };
}
