import type { ProductPriceTier } from "@/lib/price-tiers";
import { formatMoneyInput, parseMoneyInput } from "@/utils/formatters";

const EPSILON = 0.000001;

export type QuantityIntervalDraft = {
  id: string;
  quantity: string;
  price: string;
};

export type ParsedQuantityInterval = {
  quantity: number;
  totalPrice: number;
};

function parseQuantityValue(raw: string) {
  const normalized = raw.trim().replace(",", ".");
  if (!normalized) return null;
  const parsed = Number.parseFloat(normalized);
  if (!Number.isFinite(parsed) || parsed <= 0) return null;
  return Number(parsed.toFixed(3));
}

function normalizeAllowedQuantities(value: unknown): number[] {
  if (!Array.isArray(value)) return [];
  return Array.from(
    new Set(
      value
        .map((entry) => Number(entry))
        .filter((entry) => Number.isFinite(entry) && entry > 0)
        .map((entry) => Number(entry.toFixed(3)))
    )
  ).sort((a, b) => a - b);
}

function findExactTierForQuantity(quantity: number, tiers: ProductPriceTier[]) {
  return (
    tiers.find((tier) => {
      const minQty = Number(tier.min_qty);
      const maxQty = tier.max_qty === null || tier.max_qty === undefined ? null : Number(tier.max_qty);
      if (!Number.isFinite(minQty)) return false;
      if (Math.abs(minQty - quantity) > EPSILON) return false;
      if (maxQty === null || !Number.isFinite(maxQty)) return false;
      return Math.abs(maxQty - quantity) <= EPSILON;
    }) || null
  );
}

function formatQuantityValue(value: number) {
  if (Number.isInteger(value)) return String(value);
  return String(Number(value.toFixed(3))).replace(".", ",");
}

function toDraftId() {
  if (typeof crypto !== "undefined" && typeof crypto.randomUUID === "function") {
    return crypto.randomUUID();
  }
  return `interval-${Math.random().toString(16).slice(2)}-${Date.now()}`;
}

export function createQuantityIntervalDraft(values?: Partial<QuantityIntervalDraft>): QuantityIntervalDraft {
  return {
    id: values?.id || toDraftId(),
    quantity: values?.quantity || "",
    price: values?.price || "",
  };
}

export function parseQuantityIntervalsDrafts(drafts: QuantityIntervalDraft[]) {
  const parsed: ParsedQuantityInterval[] = [];
  const usedQuantities = new Set<number>();

  for (let index = 0; index < drafts.length; index += 1) {
    const row = drafts[index];
    const quantityValue = typeof row?.quantity === "string" ? row.quantity : "";
    const priceValue = typeof row?.price === "string" ? row.price : "";
    const hasAnyValue = quantityValue.trim().length > 0 || priceValue.trim().length > 0;
    if (!hasAnyValue) continue;

    const quantity = parseQuantityValue(quantityValue);
    if (quantity === null) {
      return { intervals: [] as ParsedQuantityInterval[], error: `Intervalo ${index + 1}: quantidade invalida.` };
    }

    const totalPrice = parseMoneyInput(priceValue);
    if (!Number.isFinite(totalPrice) || totalPrice <= 0) {
      return { intervals: [] as ParsedQuantityInterval[], error: `Intervalo ${index + 1}: valor invalido.` };
    }

    if (usedQuantities.has(quantity)) {
      return {
        intervals: [] as ParsedQuantityInterval[],
        error: `Intervalo ${index + 1}: quantidade ${formatQuantityValue(quantity)} duplicada.`,
      };
    }

    usedQuantities.add(quantity);
    parsed.push({
      quantity,
      totalPrice: Number(totalPrice.toFixed(2)),
    });
  }

  return {
    intervals: parsed.sort((a, b) => a.quantity - b.quantity),
    error: null as string | null,
  };
}

export function buildAllowedQuantityPricing(intervals: ParsedQuantityInterval[]) {
  const allowedQuantities = intervals.map((interval) => interval.quantity);
  const tiers: ProductPriceTier[] = intervals.map((interval, index) => ({
    min_qty: interval.quantity,
    max_qty: interval.quantity,
    unit_price: Number((interval.totalPrice / interval.quantity).toFixed(6)),
    sort_order: index,
    active: true,
  }));
  return { allowedQuantities, tiers };
}

export function hydrateQuantityIntervalsFromProduct(params: {
  allowedQuantities: unknown;
  tiers: ProductPriceTier[] | null | undefined;
  fallbackUnitPrice: number;
}) {
  const allowedQuantities = normalizeAllowedQuantities(params.allowedQuantities);
  if (allowedQuantities.length === 0) return [] as QuantityIntervalDraft[];

  const tiers = Array.isArray(params.tiers) ? params.tiers.filter((tier) => tier.active !== false) : [];
  const fallbackUnitPrice = Number.isFinite(params.fallbackUnitPrice) ? params.fallbackUnitPrice : 0;

  return allowedQuantities.map((quantity) => {
    const tier = findExactTierForQuantity(quantity, tiers);
    const totalPrice = tier
      ? (Number(tier.unit_price) || 0) * quantity
      : fallbackUnitPrice * quantity;

    return createQuantityIntervalDraft({
      quantity: formatQuantityValue(quantity),
      price: formatMoneyInput(totalPrice),
    });
  });
}
