import React from 'react';
import { Loader } from '@/app/components/ui/loader';
import { RiSubtractLine, RiAddLine } from '@remixicon/react';
import ShopPayLogo from '@/components/shopify/shop-pay-logo';
import type { ProductOption, ProductOptionValue } from '@/hooks/use-shopify-products';
import { isSwatchOptionName, swatchColorForName } from '@/config/swatches';

interface ProductPrice {
  amount: string;
  currencyCode: string;
}

interface ProductVariant {
  id: string;
  title: string;
  price: ProductPrice;
  availableForSale: boolean;
  selectedOptions: Array<{
    name: string;
    value: string;
  }>;
}

interface Product {
  id: string;
  title: string;
  description?: string;
  descriptionHtml?: string;
  handle: string;
  priceRange: {
    minVariantPrice: ProductPrice;
  };
  compareAtPriceRange?: {
    minVariantPrice: ProductPrice;
  };
  options: ProductOption[];
}

export interface ProductFeature {
  icon: string;
  label: string;
}

interface ProductDetailInfoProps {
  product: Product;
  selectedVariant: ProductVariant | null;
  selectedOptions: Record<string, string>;
  quantity: number;
  setQuantity: (quantity: number) => void;
  handleAddToCart: () => void;
  handleBuyNow?: () => void;
  onOptionChange: (optionName: string, value: string) => void;
  loading?: boolean;
  buyingNow?: boolean;
  addToCartLabel?: string;
}

// A swatch comes from the option value's own swatch (colour or image) or the
// colour its name implies (see config/swatches) — never a variant photo.
const swatchStyle = (
  value: ProductOptionValue
): { background?: string; image?: string } => {
  if (value.swatch?.color) return { background: value.swatch.color };

  const swatchImage = value.swatch?.image?.previewImage?.url;
  if (swatchImage) return { image: swatchImage };

  const namedColor = swatchColorForName(value.name);
  if (namedColor) return { background: namedColor };

  return {};
};

const ProductDetailInfo: React.FC<ProductDetailInfoProps> = ({
  product,
  selectedVariant,
  selectedOptions,
  quantity,
  setQuantity,
  handleAddToCart,
  handleBuyNow,
  onOptionChange,
  loading = false,
  buyingNow = false,
  addToCartLabel = 'Add to Cart',
}) => {
  const formatPrice = (amount: string) => {
    return `$${parseFloat(amount).toFixed(2)}`;
  };

  const price = selectedVariant?.price || product.priceRange.minVariantPrice;
  const compareAtPrice = product.compareAtPriceRange?.minVariantPrice;
  const hasDiscount =
    compareAtPrice &&
    parseFloat(compareAtPrice.amount) > parseFloat(price.amount);
  const isAvailable = selectedVariant?.availableForSale ?? false;

  const isSwatchOption = (option: ProductOption) =>
    isSwatchOptionName(option.name);

  // Some products return Size before Color; show the swatches first either way.
  const orderedOptions = [...(product.options ?? [])].sort(
    (a, b) => Number(isSwatchOption(b)) - Number(isSwatchOption(a))
  );

  // `optionValues` carries the swatch data; fall back to plain `values`.
  const optionValuesFor = (option: ProductOption): ProductOptionValue[] =>
    option.optionValues?.length
      ? option.optionValues
      : option.values.map((value) => ({ id: value, name: value }));

  return (
    <div>
      <h1 className="text-2xl md:text-3xl font-normal text-foreground">
        {product.title}
      </h1>
      <div className="flex items-baseline gap-x-3 mt-1">
        <span className="font-mono tabular-nums tracking-tight text-base text-foreground">
          {formatPrice(price.amount)}
        </span>
        {hasDiscount && compareAtPrice && (
          <span className="font-mono tabular-nums tracking-tight text-sm line-through text-muted-foreground">
            {formatPrice(compareAtPrice.amount)}
          </span>
        )}
      </div>

      {/* Product Options — colour swatches lead, whatever order the API returns */}
      {orderedOptions.map((option) => {
        const isSwatch = isSwatchOption(option);
        const selected = selectedOptions[option.name];

        return (
          <div key={option.id} className="mt-8">
            <div className="text-sm text-muted-foreground mb-2">
              {option.name}
              {isSwatch && selected && (
                <span className="text-foreground font-medium">: {selected}</span>
              )}
            </div>

            <div className="flex flex-wrap gap-2">
              {optionValuesFor(option).map((value) => {
                const isSelected = selected === value.name;

                if (isSwatch) {
                  const { background, image } = swatchStyle(value);

                  return (
                    <button
                      key={value.id}
                      onClick={() => onOptionChange(option.name, value.name)}
                      title={value.name}
                      aria-label={value.name}
                      aria-pressed={isSelected}
                      className={`h-8 w-8 rounded-full bg-cover bg-center transition-shadow ${
                        isSelected
                          ? 'ring-2 ring-foreground ring-offset-2'
                          : 'ring-1 ring-border hover:ring-foreground/40'
                      }`}
                      style={{
                        backgroundColor: background,
                        backgroundImage: image ? `url(${image})` : undefined,
                      }}
                    >
                      {!background && !image && (
                        <span className="text-[10px]">{value.name.at(0)}</span>
                      )}
                    </button>
                  );
                }

                return (
                  <button
                    key={value.id}
                    onClick={() => onOptionChange(option.name, value.name)}
                    aria-pressed={isSelected}
                    className={`min-w-14 px-5 py-2 rounded-md border text-sm text-center transition-colors ${
                      isSelected
                        ? 'border-foreground text-foreground'
                        : 'border-border text-muted-foreground hover:border-foreground hover:text-foreground'
                    }`}
                  >
                    {value.name}
                  </button>
                );
              })}
            </div>
          </div>
        );
      })}

      {/* Quantity + Add to Cart */}
      <div className="mt-8 flex items-stretch gap-3">
        <div className="flex items-center rounded-md border border-border h-11">
          <button
            onClick={() => setQuantity(Math.max(1, quantity - 1))}
            disabled={quantity <= 1}
            aria-label="Decrease quantity"
            className="h-full px-3 text-foreground disabled:text-muted-foreground/50 transition-colors"
          >
            <RiSubtractLine size={16} />
          </button>
          <span className="w-8 text-center text-sm tabular-nums">
            {quantity}
          </span>
          <button
            onClick={() => setQuantity(quantity + 1)}
            aria-label="Increase quantity"
            className="h-full px-3 text-foreground transition-colors"
          >
            <RiAddLine size={16} />
          </button>
        </div>

        <button
          onClick={handleAddToCart}
          disabled={!isAvailable || loading}
          className="flex-1 h-11 rounded-md bg-foreground text-background text-sm font-medium hover:bg-foreground/90 disabled:opacity-50 transition-colors flex items-center justify-center gap-x-2"
        >
          {loading && <Loader size={16} />}
          {isAvailable ? addToCartLabel : 'Out of Stock'}
        </button>
      </div>

      {/* Sends the shopper to the Shopify checkout, where Shop Pay is offered. */}
      {handleBuyNow && (
        <button
          type="button"
          onClick={handleBuyNow}
          disabled={!isAvailable || buyingNow}
          className="mt-3 flex h-11 w-full cursor-pointer items-center justify-center rounded-md bg-shop px-4 text-white transition-colors hover:bg-shop/85 disabled:cursor-not-allowed disabled:opacity-50"
        >
          <span className="sr-only">Buy with</span>
          {buyingNow ? <Loader size={16} /> : <ShopPayLogo />}
        </button>
      )}

      {/* Description */}
      {(product.descriptionHtml || product.description) && (
        <div className="mt-10 text-sm leading-6 text-foreground product-description">
          {product.descriptionHtml ? (
            <div
              dangerouslySetInnerHTML={{ __html: product.descriptionHtml }}
            />
          ) : (
            <p>{product.description}</p>
          )}
        </div>
      )}
    </div>
  );
};

export default ProductDetailInfo;
