'use client';

import { useRef, type ReactNode } from 'react';
import { MoreHorizontal, Download, Image as ImageIcon } from 'lucide-react';

import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu';
import { cn } from '@/lib/utils';

interface ChartCardProps {
  title: string;
  description?: string;
  /** Filename stem used for both CSV + PNG exports (no extension). */
  exportFilename: string;
  /** Returns CSV content for the current chart data, or null when nothing to export. */
  toCsv?: () => string | null;
  children: ReactNode;
  className?: string;
}

function downloadBlob(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();
  a.remove();
  URL.revokeObjectURL(url);
}

async function exportContainerAsPng(container: HTMLElement, filename: string) {
  const svg = container.querySelector('svg');
  if (!svg) return;
  const clone = svg.cloneNode(true) as SVGSVGElement;
  const { width, height } = svg.getBoundingClientRect();
  clone.setAttribute('width', String(width));
  clone.setAttribute('height', String(height));
  clone.setAttribute('xmlns', 'http://www.w3.org/2000/svg');
  const xml = new XMLSerializer().serializeToString(clone);
  const svgBlob = new Blob([xml], { type: 'image/svg+xml;charset=utf-8' });
  const url = URL.createObjectURL(svgBlob);
  const img = new Image();
  await new Promise<void>((resolve, reject) => {
    img.onload = () => resolve();
    img.onerror = () => reject(new Error('Failed to load chart for export'));
    img.src = url;
  });
  const canvas = document.createElement('canvas');
  const dpr = window.devicePixelRatio ?? 1;
  canvas.width = width * dpr;
  canvas.height = height * dpr;
  const ctx = canvas.getContext('2d');
  if (!ctx) {
    URL.revokeObjectURL(url);
    return;
  }
  ctx.scale(dpr, dpr);
  ctx.fillStyle = '#ffffff';
  ctx.fillRect(0, 0, width, height);
  ctx.drawImage(img, 0, 0, width, height);
  URL.revokeObjectURL(url);
  canvas.toBlob((blob) => {
    if (blob) downloadBlob(blob, filename);
  }, 'image/png');
}

export function ChartCard({
  title,
  description,
  exportFilename,
  toCsv,
  children,
  className,
}: ChartCardProps) {
  const containerRef = useRef<HTMLDivElement>(null);

  function onDownloadCsv() {
    const csv = toCsv?.();
    if (!csv) return;
    downloadBlob(new Blob([csv], { type: 'text/csv;charset=utf-8' }), `${exportFilename}.csv`);
  }

  function onDownloadPng() {
    if (containerRef.current) {
      void exportContainerAsPng(containerRef.current, `${exportFilename}.png`);
    }
  }

  return (
    <Card className={cn('h-full', className)}>
      <CardHeader className="flex flex-row items-start justify-between gap-2 space-y-0">
        <div>
          <CardTitle className="text-base">{title}</CardTitle>
          {description ? <p className="mt-1 text-xs text-muted-foreground">{description}</p> : null}
        </div>
        <DropdownMenu>
          <DropdownMenuTrigger asChild>
            <Button
              variant="ghost"
              size="sm"
              className="h-8 w-8 p-0"
              aria-label="Chart options"
              data-testid="chart-menu"
            >
              <MoreHorizontal className="h-4 w-4" />
            </Button>
          </DropdownMenuTrigger>
          <DropdownMenuContent align="end" className="w-44">
            {toCsv ? (
              <DropdownMenuItem onSelect={onDownloadCsv}>
                <Download className="mr-2 h-4 w-4" />
                Download CSV
              </DropdownMenuItem>
            ) : null}
            <DropdownMenuItem onSelect={onDownloadPng}>
              <ImageIcon className="mr-2 h-4 w-4" />
              Download PNG
            </DropdownMenuItem>
          </DropdownMenuContent>
        </DropdownMenu>
      </CardHeader>
      <CardContent>
        <div ref={containerRef}>{children}</div>
      </CardContent>
    </Card>
  );
}
