"use server";

import { getProductsByHandles } from "@/lib/medusa/products";
import { sanityClient } from "@/lib/sanity/client";
import { EVENT_PERSONALIZATION_KEYWORDS, type EventType } from "@/lib/event-personalization";

export interface RecommendedProduct {
  id: string;
  handle: string;
  title: string;
  priceCents: number;
  imageUrl?: string;
  salePriceCents?: number;
  regularPriceCents?: number;
  isCustomizable?: boolean;
  supportsCustomTheme?: boolean;
  themeOptions: string[];
  themeDetails: Array<{ title: string; imageUrl?: string }>;
  customThemeRequest?: {
    isEnabled?: boolean;
    optionLabel?: string;
    modalTitle?: string;
    helperText?: string;
    modalDescription?: string;
  };
}

type SanityRecommendationProduct = {
  _id: string;
  title: string;
  slug?: { current?: string };
  priceCents?: number;
  salePriceCents?: number;
  regularPriceCents?: number;
  isCustomizable?: boolean;
  eventPopupCategories?: EventType[];
  showThemes?: boolean;
  themeOptions?: string[];
  themeDetails?: Array<{ title?: string; imageUrl?: string }>;
  customThemeRequest?: {
    isEnabled?: boolean;
    optionLabel?: string;
    modalTitle?: string;
    helperText?: string;
    modalDescription?: string;
  };
  mainImage?: { asset?: { url?: string } };
  imageUrl?: string;
  gallery?: Array<{ image?: { asset?: { url?: string } }; url?: string }>;
  tags?: string[];
  categories?: string[];
};

function normalizeStringArray(values: unknown) {
  return Array.isArray(values)
    ? values.map((value) => (typeof value === "string" ? value.trim() : "")).filter(Boolean)
    : [];
}

function normalizeText(value: string) {
  return value
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .toLowerCase()
    .trim();
}

function buildSearchText(product: SanityRecommendationProduct) {
  return normalizeText(
    [
      product.title,
      ...(Array.isArray(product.tags) ? product.tags : []),
      ...(Array.isArray(product.categories) ? product.categories : []),
    ]
      .filter(Boolean)
      .join(" "),
  );
}

export async function getEventRecommendedProducts(
  eventType: EventType,
  limit = 6,
): Promise<RecommendedProduct[]> {
  if (!sanityClient) {
    return [];
  }

  const products = await sanityClient.fetch<SanityRecommendationProduct[]>(
    `*[
      _type == "product" &&
      defined(slug.current) &&
      status == "publish" &&
      coalesce(isActive, true) == true
    ][0...$maxDocuments] | order(title asc) {
      _id,
      title,
      slug,
      priceCents,
      salePriceCents,
      regularPriceCents,
      "isCustomizable": coalesce(isCustomizable, true),
      eventPopupCategories,
      "showThemes": coalesce(showThemes, false),
      "themeDetails": select(
        showThemes == true => themes[defined(@->title) && coalesce(@->isActive, true) == true]->{
          title,
          imageUrl
        },
        []
      ),
      "themeOptions": select(
        showThemes == true => themes[defined(@->title) && coalesce(@->isActive, true) == true]->title,
        []
      ),
      "customThemeRequest": customThemeRequest{
        "isEnabled": coalesce(isEnabled, true),
        optionLabel,
        modalTitle,
        helperText,
        modalDescription
      },
      mainImage{
        asset->{
          url
        }
      },
      imageUrl,
      gallery[0]{
        image{
          asset->{
            url
          }
        },
        url
      },
      tags,
      "categories": categories[@->isActive != false]->title
    }`,
    {
      maxDocuments: 250,
    },
  );

  const availableStoreProducts = await getProductsByHandles(
    products
      .map((product) => product.slug?.current || "")
      .filter(Boolean),
  );
  const storeProductsByHandle = new Map(
    availableStoreProducts
      .map((product) => [String(product.handle || "").trim(), product] as const)
      .filter(([handle]) => Boolean(handle)),
  );

  const availableHandles = new Set(
    availableStoreProducts
      .filter((product) => Array.isArray(product.variants) && product.variants.some((variant) => typeof variant.id === "string" && variant.id.trim()))
      .map((product) => (product.handle || "").trim())
      .filter(Boolean),
  );

  const availableProducts = products.filter((product) => {
    const handle = (product.slug?.current || "").trim();
    return Boolean(handle) && availableHandles.has(handle);
  });

  const explicitMatches = availableProducts.filter((product) =>
    Array.isArray(product.eventPopupCategories) && product.eventPopupCategories.includes(eventType),
  );

  const matchingProducts =
    explicitMatches.length > 0
      ? explicitMatches
      : availableProducts
          .map((product) => {
            const searchText = buildSearchText(product);
            const score = EVENT_PERSONALIZATION_KEYWORDS[eventType].reduce((total, keyword) => {
              const normalizedKeyword = normalizeText(keyword);
              return searchText.includes(normalizedKeyword) ? total + normalizedKeyword.length : total;
            }, 0);

            return { product, score };
          })
          .filter((entry) => entry.score > 0)
          .sort((left, right) => right.score - left.score || left.product.title.localeCompare(right.product.title, "fr"))
          .map((entry) => entry.product);

  const fallbackProducts =
    matchingProducts.length > 0
      ? matchingProducts
      : availableProducts.filter((product) => product.isCustomizable !== false);

  return fallbackProducts.slice(0, limit).map((product) => {
    const handle = product.slug?.current || product._id;
    const storeProduct = storeProductsByHandle.get(handle);
    const productMetadata =
      storeProduct?.metadata && typeof storeProduct.metadata === "object" ? (storeProduct.metadata as Record<string, unknown>) : {};
    const medusaThemeOptions = normalizeStringArray(productMetadata.theme_options);
    const sanityThemeOptions = normalizeStringArray(product.themeOptions);
    const themeOptions =
      product.showThemes === true
        ? sanityThemeOptions
        : sanityThemeOptions.length > 0
          ? sanityThemeOptions
          : medusaThemeOptions;
    const themeDetails = Array.isArray(product.themeDetails)
      ? product.themeDetails
          .filter((item) => item && typeof item.title === "string" && item.title.trim())
          .map((item) => ({
            title: String(item.title || "").trim(),
            imageUrl: typeof item.imageUrl === "string" ? item.imageUrl.trim() || undefined : undefined,
          }))
      : [];

    return {
      id: product._id,
      handle,
      title: product.title,
      priceCents: product.salePriceCents || product.priceCents || product.regularPriceCents || 0,
      salePriceCents: product.salePriceCents,
      regularPriceCents: product.regularPriceCents,
      isCustomizable: product.isCustomizable !== false,
      supportsCustomTheme: productMetadata.supports_custom_theme !== false,
      themeOptions,
      themeDetails,
      customThemeRequest: product.customThemeRequest,
      imageUrl:
        product.imageUrl ||
        product.mainImage?.asset?.url ||
        product.gallery?.[0]?.url ||
        product.gallery?.[0]?.image?.asset?.url,
    };
  });
}
