import { HttpTypes } from "@medusajs/types";
import { env } from "@/lib/env";
import { hasFreeShipping } from "@/lib/utils/cart-pricing";

type MondialRelayRateTier = {
  maxWeightKg: number;
  amount: number;
};

type PackageEstimate = {
  weightKg: number;
  lengthCm: number;
  widthCm: number;
  heightCm: number;
};

export type MondialRelayQuote = {
  amount: number | null;
  weightKg: number;
  lengthCm: number;
  widthCm: number;
  heightCm: number;
  reason: string | null;
};

const DEFAULT_RATE_TIERS: MondialRelayRateTier[] = [
  { maxWeightKg: 0.25, amount: 410 },
  { maxWeightKg: 0.5, amount: 410 },
  { maxWeightKg: 0.75, amount: 510 },
  { maxWeightKg: 1, amount: 510 },
  { maxWeightKg: 2, amount: 660 },
  { maxWeightKg: 4, amount: 799 },
  { maxWeightKg: 5, amount: 1599 },
  { maxWeightKg: 7, amount: 1599 },
  { maxWeightKg: 10, amount: 1599 },
  { maxWeightKg: 15, amount: 2299 },
  { maxWeightKg: 25, amount: 2299 },
];

const MAX_WEIGHT_KG = 25;
const MAX_LENGTH_CM = 120;
const MAX_DEVELOPED_DIMENSION_CM = 150;

function asNumber(value: unknown) {
  if (typeof value === "number" && Number.isFinite(value)) {
    return value;
  }
  if (typeof value === "string") {
    const normalized = value.trim().replace(",", ".");
    if (!normalized) {
      return null;
    }
    const parsed = Number(normalized);
    if (Number.isFinite(parsed)) {
      return parsed;
    }
  }
  return null;
}

function getRateTiers() {
  const raw = env.mondialRelayRateCardJson.trim();
  if (!raw) {
    return DEFAULT_RATE_TIERS;
  }

  try {
    const parsed = JSON.parse(raw) as Array<{ maxWeightKg?: unknown; amount?: unknown }>;
    const tiers = parsed
      .map((tier) => ({
        maxWeightKg: asNumber(tier.maxWeightKg),
        amount: asNumber(tier.amount),
      }))
      .filter((tier): tier is { maxWeightKg: number; amount: number } => tier.maxWeightKg !== null && tier.amount !== null)
      .sort((a, b) => a.maxWeightKg - b.maxWeightKg);

    return tiers.length ? tiers : DEFAULT_RATE_TIERS;
  } catch {
    return DEFAULT_RATE_TIERS;
  }
}

function convertWeightToKg(weight: number) {
  const unit = env.mondialRelayWeightUnit.trim().toLowerCase();
  if (unit === "kg") {
    return weight;
  }
  return weight / 1000;
}

function getDefaultWeightKg() {
  const fallback = asNumber(env.mondialRelayDefaultItemWeight);
  if (fallback === null || fallback <= 0) {
    return 0.1;
  }
  return convertWeightToKg(fallback);
}

function getDefaultDimensionCm(raw: string, defaultValue: number) {
  const parsed = asNumber(raw);
  if (parsed === null || parsed <= 0) {
    return defaultValue;
  }
  return parsed;
}

function estimatePackage(cart: HttpTypes.StoreCart): PackageEstimate {
  let totalWeightKg = 0;
  let maxLengthCm = 0;
  let maxWidthCm = 0;
  let totalHeightCm = 0;

  const defaultWeightKg = getDefaultWeightKg();
  const defaultLengthCm = getDefaultDimensionCm(env.mondialRelayDefaultLengthCm, 10);
  const defaultWidthCm = getDefaultDimensionCm(env.mondialRelayDefaultWidthCm, 10);
  const defaultHeightCm = getDefaultDimensionCm(env.mondialRelayDefaultHeightCm, 2);

  for (const item of cart.items || []) {
    const quantity = Math.max(1, item.quantity || 1);
    const variant = (item as { variant?: Record<string, unknown> }).variant || {};
    const product = (item as { product?: Record<string, unknown> }).product || {};

    const weight = asNumber(variant.weight) ?? asNumber(product.weight);
    if (weight !== null && weight > 0) {
      totalWeightKg += convertWeightToKg(weight) * quantity;
    } else {
      totalWeightKg += defaultWeightKg * quantity;
    }

    const length = asNumber(variant.length) ?? asNumber(product.length);
    const width = asNumber(variant.width) ?? asNumber(product.width);
    const height = asNumber(variant.height) ?? asNumber(product.height);

    maxLengthCm = Math.max(maxLengthCm, length !== null && length > 0 ? length : defaultLengthCm);
    maxWidthCm = Math.max(maxWidthCm, width !== null && width > 0 ? width : defaultWidthCm);
    totalHeightCm += (height !== null && height > 0 ? height : defaultHeightCm) * quantity;
  }

  return {
    weightKg: totalWeightKg,
    lengthCm: maxLengthCm,
    widthCm: maxWidthCm,
    heightCm: totalHeightCm,
  };
}

export function getMondialRelayQuote(cart: HttpTypes.StoreCart): MondialRelayQuote {
  if (hasFreeShipping(cart.subtotal)) {
    return { amount: 0, weightKg: 0, lengthCm: 0, widthCm: 0, heightCm: 0, reason: null };
  }

  const estimate = estimatePackage(cart);
  const developed = estimate.lengthCm + estimate.widthCm + estimate.heightCm;

  if (estimate.weightKg <= 0) {
    return { ...estimate, amount: null, reason: "Poids produit manquant." };
  }

  if (estimate.weightKg > MAX_WEIGHT_KG) {
    return { ...estimate, amount: null, reason: "Poids total au-dessus de la limite Mondial Relay (25 kg)." };
  }

  if (estimate.lengthCm > MAX_LENGTH_CM) {
    return { ...estimate, amount: null, reason: "Longueur colis au-dessus de la limite Mondial Relay (120 cm)." };
  }

  if (developed > MAX_DEVELOPED_DIMENSION_CM) {
    return { ...estimate, amount: null, reason: "Dimensions colis au-dessus de la limite Mondial Relay (L + l + h > 150 cm)." };
  }

  const tiers = getRateTiers();
  const tier = tiers.find((candidate) => estimate.weightKg <= candidate.maxWeightKg);

  if (!tier) {
    return { ...estimate, amount: null, reason: "Aucun tarif Mondial Relay applicable pour ce colis." };
  }

  return { ...estimate, amount: tier.amount, reason: null };
}
