"use client";

import React, { useMemo, useCallback, memo } from "react";
import { Button } from "@/components/ui/button";
import Link from "next/link";
import { cn } from "@/lib/utils";

type Variant = {
  product_id: string;
  [key: string]: string;
};

type ProductVariantSelectorProps = {
  variants: Variant[];
  attributes: Variant;
};

export const ProductVariantSelector: React.FC<ProductVariantSelectorProps> = memo(
  ({ variants, attributes }) => {
    /**
     * ⚡ Optimization: Memoize collected attribute values.
     * Prevents re-scanning variants array and re-sorting values on every render.
     */
    const collectedValues = useMemo(() => {
      const allValues: { [key: string]: Set<string> } = {};

      variants.forEach((variant) => {
        Object.keys(variant).forEach((key) => {
          if (key !== "product_id") {
            if (!allValues[key]) {
              allValues[key] = new Set();
            }
            allValues[key].add(variant[key]);
          }
        });
      });

      return Object.fromEntries(
        Object.entries(allValues).map(([key, valueSet]) => [
          key,
          Array.from(valueSet).sort(),
        ])
      );
    }, [variants]);

    /**
     * ⚡ Optimization: Memoize variant associations.
     * Calculates the differences between the current product and all variants once per variants/attributes change.
     */
    const associatedProductID = useMemo(() => {
      return variants.map((variant) => {
        const diff = Object.keys(variant).reduce((acc, key) => {
          if (variant[key] !== attributes[key]) {
            acc[key] = variant[key];
          }
          return acc;
        }, {} as { [key: string]: string });
        return { ...diff, product_id: variant.product_id };
      });
    }, [variants, attributes]);

    /**
     * ⚡ Optimization: Memoize helper functions.
     */
    const findVariantByAttribute = useCallback(
      (key: string, value: string) => {
        // 1. Create a target set of attributes (current attributes + the new selection)
        const targetAttributes = { ...attributes, [key]: value };

        // 2. Rank variants by how many target attributes they match
        const rankedVariants = variants.map((v) => {
          let matches = 0;
          Object.entries(targetAttributes).forEach(([attrKey, attrVal]) => {
            if (attrKey !== "product_id" && v[attrKey] === attrVal) {
              matches++;
            }
          });
          return { variant: v, matches };
        });

        // 3. Sort by matches (descending) and return the best fit
        // If the new selection is valid, the top match will have the most attributes in common.
        rankedVariants.sort((a, b) => b.matches - a.matches);
        
        return rankedVariants[0]?.variant || null;
      },
      [variants, attributes]
    );

    return (
      <div>
        <div className="flex flex-col gap-4">
          {Object.entries(collectedValues).map(([key, value]) => {
            return (
              <div key={key}>
                <h2 className="text-sm mb-2 flex items-center space-x-1">
                  <span className="text-gray-600">{key}:</span>
                  <span className="font-bold">{attributes[key]}</span>
                </h2>
                <div className="flex flex-wrap gap-2" aria-label={`${key} auswählen`}>
                  {value.map((val) => {
                    const bestVariant = findVariantByAttribute(key, val);
                    const isActive = attributes[key] === val;
                    const href = bestVariant
                      ? `/product/${bestVariant.product_id}`
                      : `/product/${attributes.product_id}`;

                    return (
                      <Button
                        key={val}
                        variant="outline"
                        asChild
                        className={cn(
                          "transition-all",
                          isActive && "border-black ring-1 ring-black ring-inset hover:bg-white"
                        )}
                        aria-current={isActive ? "true" : undefined}
                      >
                        <Link
                          href={href}
                          aria-label={`${key} ${val}${isActive ? " (ausgewählt)" : ""}`}
                        >
                          {val}
                        </Link>
                      </Button>
                    );
                  })}
                </div>
              </div>
            );
          })}
        </div>
      </div>
    );
  }
);

ProductVariantSelector.displayName = "ProductVariantSelector";
