// Security: SVG icon sources are validated and cleaned via SVGO on the server (icon-renderer.ts).
// Pattern mirrors MarkdownBody.tsx mermaid SVG rendering (dangerouslySetInnerHTML on trusted, server-cleaned SVG).
import { Card } from "@/components/ui/card";
import { Checkbox } from "@/components/ui/checkbox";
import { Button } from "@/components/ui/button";

interface Icon {
  name: string;
  svgSource: string;
  pngs: Record<string, string>;
}

interface IconResultGridProps {
  icons: Icon[];
  selectedIds: Set<string>;
  onToggle: (name: string) => void;
}

function base64ToBlob(base64: string, mimeType: string): Blob {
  const byteString = atob(base64);
  const ab = new ArrayBuffer(byteString.length);
  const ia = new Uint8Array(ab);
  for (let i = 0; i < byteString.length; i++) {
    ia[i] = byteString.charCodeAt(i);
  }
  return new Blob([ab], { type: mimeType });
}

function triggerDownload(blob: Blob, filename: string) {
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = filename;
  document.body.appendChild(a);
  a.click();
  document.body.removeChild(a);
  URL.revokeObjectURL(url);
}

function IconCard({ icon, selected, onToggle }: { icon: Icon; selected: boolean; onToggle: () => void }) {
  function handleDownloadSvg() {
    const blob = new Blob([icon.svgSource], { type: "image/svg+xml" });
    triggerDownload(blob, `${icon.name}.svg`);
  }

  function handleDownloadPng(size: string) {
    const pngData = icon.pngs[size];
    if (!pngData) return;
    const blob = base64ToBlob(pngData, "image/png");
    triggerDownload(blob, `${icon.name}-${size}.png`);
  }

  return (
    <Card className="group relative flex flex-col items-center p-3 gap-2 overflow-hidden bg-card">
      <div className="absolute top-2 left-2 opacity-0 group-hover:opacity-100 [@media(pointer:coarse)]:opacity-100 transition-opacity">
        <Checkbox
          checked={selected}
          onCheckedChange={onToggle}
          aria-label={`Select ${icon.name}`}
          className="size-4"
        />
      </div>

      {/* Server-cleaned SVG icon source rendered as trusted HTML (SVGO-validated on server) */}
      {/* eslint-disable-next-line react/no-danger */}
      <div
        className="size-12 flex items-center justify-center [&>svg]:size-full"
        dangerouslySetInnerHTML={{ __html: icon.svgSource }}
      />

      <span className="text-xs text-center truncate w-full">{icon.name}</span>

      <div className="absolute bottom-0 inset-x-0 flex gap-1 p-1 bg-card/95 opacity-0 group-hover:opacity-100 transition-opacity justify-center flex-wrap">
        <Button type="button" variant="ghost" size="sm" className="text-xs h-6 px-1.5" onClick={handleDownloadSvg}>
          SVG
        </Button>
        <Button type="button" variant="ghost" size="sm" className="text-xs h-6 px-1.5" onClick={() => handleDownloadPng("16")}>
          PNG 16
        </Button>
        <Button type="button" variant="ghost" size="sm" className="text-xs h-6 px-1.5" onClick={() => handleDownloadPng("32")}>
          PNG 32
        </Button>
        <Button type="button" variant="ghost" size="sm" className="text-xs h-6 px-1.5" onClick={() => handleDownloadPng("64")}>
          PNG 64
        </Button>
      </div>
    </Card>
  );
}

export function IconResultGrid({ icons, selectedIds, onToggle }: IconResultGridProps) {
  if (icons.length === 0) return null;

  return (
    <div className="grid grid-cols-2 md:grid-cols-4 gap-3">
      {icons.map((icon) => (
        <IconCard
          key={icon.name}
          icon={icon}
          selected={selectedIds.has(icon.name)}
          onToggle={() => onToggle(icon.name)}
        />
      ))}
    </div>
  );
}
