import { cn } from "@decocms/ui/lib/utils.ts";
import { Container } from "@untitledui/icons";
import { useState, type ReactNode } from "react";
import { AgentAvatar, type AgentAvatarSize } from "./agent-icon";

interface IntegrationIconProps {
  icon: string | null | undefined;
  name: string;
  size?: Size;
  className?: string;
  fallbackIcon?: ReactNode;
  /**
   * How the logo fills the box. "cover" (default) crops to fill edge-to-edge;
   * "contain" fits the whole logo inside, which pairs with container padding
   * to give the logo breathing room.
   */
  fit?: "cover" | "contain";
}

const SIZE_CLASSES = {
  "2xs": "h-4 w-4",
  xs: "h-6 w-6",
  sm: "h-9 w-9",
  md: "h-12 w-12",
  lg: "h-16 w-16",
  xl: "h-14 w-14",
};

type Size = keyof typeof SIZE_CLASSES;

const MIN_WIDTH_CLASSES: Record<Size, string> = {
  "2xs": "min-w-4",
  xs: "min-w-6",
  sm: "min-w-9",
  md: "min-w-12",
  lg: "min-w-16",
  xl: "min-w-14",
};

const ICON_SIZES: Record<Size, number> = {
  "2xs": 8,
  xs: 12,
  sm: 16,
  md: 24,
  lg: 32,
  xl: 28,
};

/** Map IntegrationIcon size to AgentAvatar size */
const AGENT_SIZE_MAP: Record<Size, AgentAvatarSize> = {
  "2xs": "xs",
  xs: "xs",
  sm: "sm",
  md: "md",
  lg: "lg",
  xl: "lg",
};

export function IntegrationIcon({
  icon,
  name,
  size = "md",
  className,
  fallbackIcon,
  fit = "cover",
}: IntegrationIconProps) {
  // Delegate icon:// and URL-with-color to AgentAvatar for colored rendering
  if (icon?.startsWith("icon://") || icon?.includes("#agentcolor=")) {
    return (
      <AgentAvatar
        icon={icon}
        name={name}
        size={AGENT_SIZE_MAP[size]}
        className={className}
      />
    );
  }

  // Key the stateful subtree by `icon` so load state resets whenever the icon URL changes,
  // without needing effects.
  return (
    <IntegrationIconStateful
      key={icon ?? "no-icon"}
      icon={icon}
      name={name}
      size={size}
      className={className}
      fallbackIcon={fallbackIcon}
      fit={fit}
    />
  );
}

function IntegrationIconStateful({
  icon,
  name,
  size = "md",
  className,
  fallbackIcon,
  fit = "cover",
}: IntegrationIconProps) {
  const [loaded, setLoaded] = useState(false);
  const showImage = Boolean(icon) && loaded;

  return (
    <div
      className={cn(
        "rounded-lg border border-border shrink-0 overflow-hidden aspect-square bg-white",
        SIZE_CLASSES[size],
        MIN_WIDTH_CLASSES[size],
        className,
      )}
    >
      <img
        src={icon || undefined}
        alt={name}
        className={cn(
          "h-full w-full",
          fit === "contain" ? "object-contain" : "object-cover",
          !showImage && "hidden",
        )}
        onError={() => setLoaded(false)}
        onLoad={() => setLoaded(true)}
      />

      {/* Fallback: muted icon with connection symbol */}
      <div
        className={cn(
          "h-full w-full flex items-center justify-center bg-muted/20",
          showImage && "hidden",
        )}
      >
        {fallbackIcon ?? (
          <Container
            size={ICON_SIZES[size]}
            className="text-muted-foreground"
          />
        )}
      </div>
    </div>
  );
}
