import type { Product, ProductVariant } from "@/data/products";
import { products as localProducts } from "@/data/products";

const MEDUSA_URL =
  process.env.NEXT_PUBLIC_MEDUSA_BACKEND_URL || "https://ot.azulado.cloud";
const PUBLISHABLE_KEY =
  process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "";
/** Región Colombia (COP) — precios calculados de Medusa */
export const REGION_ID =
  process.env.NEXT_PUBLIC_MEDUSA_REGION_ID ||
  "reg_01KZYB6J2XPG5MNBMQERN9MHAJ";

type MedusaImage = { url?: string };
type MedusaOption = {
  title?: string;
  values?: { value?: string }[];
};
type MedusaVariant = {
  id?: string;
  title?: string;
  inventory_quantity?: number | null;
  manage_inventory?: boolean | null;
  calculated_price?: {
    calculated_amount?: number;
    currency_code?: string;
  };
  prices?: { amount?: number; currency_code?: string }[];
  options?: {
    value?: string;
    option?: { title?: string };
  }[];
};

type MedusaProduct = {
  id: string;
  title: string;
  handle: string;
  description?: string | null;
  thumbnail?: string | null;
  images?: MedusaImage[];
  options?: MedusaOption[];
  variants?: MedusaVariant[];
  metadata?: Record<string, string | number | boolean | null> | null;
};

function headers() {
  return {
    "Content-Type": "application/json",
    "x-publishable-api-key": PUBLISHABLE_KEY,
  };
}

function extractOptionValues(product: MedusaProduct, title: string) {
  const opt = (product.options || []).find(
    (o) => o.title?.toLowerCase() === title.toLowerCase()
  );
  return (opt?.values || []).map((v) => v.value).filter(Boolean) as string[];
}

function variantPrice(variant: MedusaVariant) {
  const calculated = variant.calculated_price?.calculated_amount;
  if (typeof calculated === "number") return calculated;
  const cop = variant.prices?.find((p) => p.currency_code === "cop")?.amount;
  if (typeof cop === "number") return cop;
  const any = variant.prices?.[0]?.amount;
  return typeof any === "number" ? any : 0;
}

function mapVariant(variant: MedusaVariant): ProductVariant {
  const fromOptions: Record<string, string> = {};
  for (const opt of variant.options || []) {
    const title = opt.option?.title?.toLowerCase() || "";
    if (title && opt.value) fromOptions[title] = opt.value;
  }
  const parts = (variant.title || "").split(" / ").map((p) => p.trim());
  const sizeDama = fromOptions["talla dama"];
  const sizeCaballero = fromOptions["talla caballero"];
  const color =
    fromOptions.color ||
    parts[parts.length - 1] ||
    "Único";

  if (sizeDama && sizeCaballero) {
    return {
      id: variant.id || "",
      size: `Dama ${sizeDama} · Caballero ${sizeCaballero}`,
      sizeDama,
      sizeCaballero,
      color,
      price: variantPrice(variant),
      inventory_quantity:
        typeof variant.inventory_quantity === "number"
          ? variant.inventory_quantity
          : null,
      manage_inventory: Boolean(variant.manage_inventory),
    };
  }

  return {
    id: variant.id || "",
    size: fromOptions.talla || parts[0] || "U",
    color: fromOptions.color || parts[1] || "Único",
    price: variantPrice(variant),
    inventory_quantity:
      typeof variant.inventory_quantity === "number"
        ? variant.inventory_quantity
        : null,
    manage_inventory: Boolean(variant.manage_inventory),
  };
}

function extractPrice(product: MedusaProduct) {
  const variant = product.variants?.[0];
  return variant ? variantPrice(variant) : 0;
}

export function mapMedusaProduct(p: MedusaProduct): Product {
  const images = (p.images || [])
    .map((i) => i.url)
    .filter(Boolean) as string[];
  if (!images.length && p.thumbnail) images.push(p.thumbnail);

  const sizesDama = extractOptionValues(p, "Talla Dama");
  const sizesCaballero = extractOptionValues(p, "Talla Caballero");
  const sizes = sizesDama.length
    ? sizesDama
    : extractOptionValues(p, "Talla");
  const colors = extractOptionValues(p, "Color");
  const meta = p.metadata || {};
  const variants = (p.variants || [])
    .map(mapVariant)
    .filter((v) => v.id);

  const parseMetaJson = <T,>(raw: unknown): T | null => {
    if (raw == null) return null;
    if (typeof raw === "string") {
      try {
        return JSON.parse(raw) as T;
      } catch {
        return null;
      }
    }
    if (typeof raw === "object") return raw as T;
    return null;
  };

  type MetaWay = {
    name: string;
    tagline?: string;
    swatches?: string[];
    images?: string[];
  };
  const rawWays = parseMetaJson<MetaWay[]>(meta.color_ways);
  const editorialColorWays = (rawWays || [])
    .filter((w) => w?.name)
    .map((w) => ({
      name: w.name,
      tagline: w.tagline,
      swatches: (w.swatches || []).filter(Boolean),
      images: (w.images || []).filter(Boolean),
    }));
  const editorialSpecs =
    parseMetaJson<{ label: string; value: string }[]>(meta.specs) || undefined;

  const colorNames = editorialColorWays.length
    ? editorialColorWays.map((w) => w.name)
    : colors;

  return {
    id: p.id,
    slug: p.handle,
    name: p.title,
    category: (String(meta.category || "mujer") as Product["category"]),
    collection: String(meta.collection || "OLD TENNIS"),
    price: extractPrice(p),
    description: p.description || "",
    colors: colorNames.length ? colorNames : ["Único"],
    sizes: sizes.length ? sizes : ["U"],
    ...(sizesDama.length ? { sizesDama } : {}),
    ...(sizesCaballero.length ? { sizesCaballero } : {}),
    images: images.length ? images : ["/brand/senora-clasica.jpg"],
    tagline: meta.tagline ? String(meta.tagline) : undefined,
    variants,
    ...(editorialColorWays.length ? { editorialColorWays } : {}),
    ...(editorialSpecs?.length ? { editorialSpecs } : {}),
  };
}

const PRODUCT_FIELDS =
  "*variants,*variants.calculated_price,*variants.options,*variants.options.option,*images,*options,*options.values,+metadata,+variants.inventory_quantity,+variants.manage_inventory";

export async function fetchStoreProducts(): Promise<Product[]> {
  if (!PUBLISHABLE_KEY) return localProducts;
  try {
    const qs = new URLSearchParams({
      limit: "50",
      region_id: REGION_ID,
      fields: PRODUCT_FIELDS,
    });
    const res = await fetch(`${MEDUSA_URL}/store/products?${qs}`, {
      headers: headers(),
      next: { revalidate: 15 },
    });
    if (!res.ok) throw new Error(`Medusa ${res.status}`);
    const data = await res.json();
    const mapped = (data.products || []).map(mapMedusaProduct);
    return mapped.length ? mapped : localProducts;
  } catch {
    return localProducts;
  }
}

export async function fetchStoreProduct(handle: string): Promise<Product | null> {
  const normalized = handle.trim().toLowerCase().replaceAll("_", "-");
  const tryHandles = normalized === handle ? [handle] : [normalized, handle];

  if (!PUBLISHABLE_KEY) {
    return (
      localProducts.find((p) => tryHandles.includes(p.slug)) || null
    );
  }
  try {
    for (const h of tryHandles) {
      const qs = new URLSearchParams({
        handle: h,
        region_id: REGION_ID,
        fields: PRODUCT_FIELDS,
      });
      const res = await fetch(`${MEDUSA_URL}/store/products?${qs}`, {
        headers: headers(),
        next: { revalidate: 15 },
      });
      if (!res.ok) continue;
      const data = await res.json();
      const p = data.products?.[0];
      if (p) return mapMedusaProduct(p);
    }
    return localProducts.find((x) => tryHandles.includes(x.slug)) || null;
  } catch {
    return localProducts.find((p) => tryHandles.includes(p.slug)) || null;
  }
}
