/**
 * WhiteboardCanvas — SVG-based whiteboard for classroom scene rendering.
 *
 * Supports incremental drawing operations:
 * - Text (positioned labels)
 * - Shapes (rectangles, circles, arrows)
 * - Charts (bar/line/pie via simple SVG)
 * - LaTeX (rendered as styled text blocks)
 */

import { useCallback } from 'react';
import type { SceneAction } from '../../types/classroom';

interface WhiteboardCanvasProps {
  items: WhiteboardItem[];
  width?: number;
  height?: number;
}

export interface WhiteboardItem {
  type: string;
  data: SceneAction;
}

export function WhiteboardCanvas({
  items,
  width = 800,
  height = 600,
}: WhiteboardCanvasProps) {
  const renderItem = useCallback((item: WhiteboardItem, index: number) => {
    switch (item.type) {
      case 'whiteboard_draw_text':
        return <TextItem key={index} data={item.data as TextDrawData} />;
      case 'whiteboard_draw_shape':
        return <ShapeItem key={index} data={item.data as ShapeDrawData} />;
      case 'whiteboard_draw_chart':
        return <ChartItem key={index} data={item.data as ChartDrawData} />;
      case 'whiteboard_draw_latex':
        return <LatexItem key={index} data={item.data as LatexDrawData} />;
      default:
        return null;
    }
  }, []);

  return (
    <div className="w-full h-full border border-gray-200 dark:border-gray-700 rounded-lg bg-white dark:bg-gray-900 overflow-auto">
      <svg
        viewBox={`0 0 ${width} ${height}`}
        className="w-full h-full"
        xmlns="http://www.w3.org/2000/svg"
      >
        {/* Grid background */}
        <defs>
          <pattern id="grid" width="40" height="40" patternUnits="userSpaceOnUse">
            <path d="M 40 0 L 0 0 0 40" fill="none" stroke="#f0f0f0" strokeWidth="0.5" />
          </pattern>
        </defs>
        <rect width={width} height={height} fill="url(#grid)" />

        {/* Rendered items */}
        {items.map((item, i) => renderItem(item, i))}
      </svg>
    </div>
  );
}

// ---------------------------------------------------------------------------
// Sub-components
// ---------------------------------------------------------------------------

interface TextDrawData {
  type: 'whiteboard_draw_text';
  x: number;
  y: number;
  text: string;
  fontSize?: number;
  color?: string;
}

function TextItem({ data }: { data: TextDrawData }) {
  return (
    <text
      x={data.x}
      y={data.y}
      fontSize={data.fontSize ?? 16}
      fill={data.color ?? '#333333'}
      fontFamily="system-ui, sans-serif"
    >
      {data.text}
    </text>
  );
}

interface ShapeDrawData {
  type: 'whiteboard_draw_shape';
  shape: string;
  x: number;
  y: number;
  width: number;
  height: number;
  fill?: string;
}

function ShapeItem({ data }: { data: ShapeDrawData }) {
  switch (data.shape) {
    case 'circle':
      return (
        <ellipse
          cx={data.x + data.width / 2}
          cy={data.y + data.height / 2}
          rx={data.width / 2}
          ry={data.height / 2}
          fill={data.fill ?? '#e5e7eb'}
          stroke="#9ca3af"
          strokeWidth={1}
        />
      );
    case 'arrow':
      return (
        <g>
          <line
            x1={data.x}
            y1={data.y + data.height / 2}
            x2={data.x + data.width}
            y2={data.y + data.height / 2}
            stroke={data.fill ?? '#6b7280'}
            strokeWidth={2}
            markerEnd="url(#arrowhead)"
          />
          <defs>
            <marker id="arrowhead" markerWidth="10" markerHeight="7" refX="10" refY="3.5" orient="auto">
              <polygon points="0 0, 10 3.5, 0 7" fill={data.fill ?? '#6b7280'} />
            </marker>
          </defs>
        </g>
      );
    default: // rectangle
      return (
        <rect
          x={data.x}
          y={data.y}
          width={data.width}
          height={data.height}
          fill={data.fill ?? '#e5e7eb'}
          stroke="#9ca3af"
          strokeWidth={1}
          rx={4}
        />
      );
  }
}

interface ChartDrawData {
  type: 'whiteboard_draw_chart';
  chartType: string;
  data: Record<string, unknown>;
  x: number;
  y: number;
  width: number;
  height: number;
}

function ChartItem({ data }: { data: ChartDrawData }) {
  const chartData = data.data;
  const labels = (chartData?.labels as string[]) ?? [];
  const values = (chartData?.values as number[]) ?? [];

  if (labels.length === 0 || values.length === 0) return null;

  switch (data.chartType) {
    case 'bar':
      return <BarChart data={data} labels={labels} values={values} />;
    case 'line':
      return <LineChart data={data} labels={labels} values={values} />;
    default:
      return <BarChart data={data} labels={labels} values={values} />;
  }
}

function BarChart({ data, labels, values }: {
  data: ChartDrawData;
  labels: string[];
  values: number[];
}) {
  const maxVal = Math.max(...values, 1);
  const barWidth = data.width / (labels.length * 2);
  const chartHeight = data.height - 30;

  return (
    <g transform={`translate(${data.x}, ${data.y})`}>
      {values.map((val, i) => {
        const barHeight = (val / maxVal) * chartHeight;
        return (
          <g key={i}>
            <rect
              x={i * (barWidth * 2) + barWidth / 2}
              y={chartHeight - barHeight}
              width={barWidth}
              height={barHeight}
              fill="#6366f1"
              rx={2}
            />
            <text
              x={i * (barWidth * 2) + barWidth}
              y={data.height - 5}
              textAnchor="middle"
              fontSize={10}
              fill="#666"
            >
              {labels[i]}
            </text>
          </g>
        );
      })}
    </g>
  );
}

function LineChart({ data, labels, values }: {
  data: ChartDrawData;
  labels: string[];
  values: number[];
}) {
  const maxVal = Math.max(...values, 1);
  const chartHeight = data.height - 30;
  const stepX = data.width / Math.max(labels.length - 1, 1);

  const points = values.map((val, i) => {
    const x = i * stepX;
    const y = chartHeight - (val / maxVal) * chartHeight;
    return `${x},${y}`;
  }).join(' ');

  return (
    <g transform={`translate(${data.x}, ${data.y})`}>
      <polyline
        points={points}
        fill="none"
        stroke="#6366f1"
        strokeWidth={2}
      />
      {values.map((val, i) => {
        const x = i * stepX;
        const y = chartHeight - (val / maxVal) * chartHeight;
        return (
          <g key={i}>
            <circle cx={x} cy={y} r={3} fill="#6366f1" />
            <text
              x={x}
              y={data.height - 5}
              textAnchor="middle"
              fontSize={10}
              fill="#666"
            >
              {labels[i]}
            </text>
          </g>
        );
      })}
    </g>
  );
}

interface LatexDrawData {
  type: 'whiteboard_draw_latex';
  latex: string;
  x: number;
  y: number;
}

function LatexItem({ data }: { data: LatexDrawData }) {
  return (
    <g transform={`translate(${data.x}, ${data.y})`}>
      <rect
        x={-4}
        y={-20}
        width={data.latex.length * 10 + 8}
        height={28}
        fill="#fef3c7"
        stroke="#f59e0b"
        strokeWidth={1}
        rx={4}
      />
      <text
        x={0}
        y={0}
        fontSize={14}
        fill="#92400e"
        fontFamily="'Courier New', monospace"
      >
        {data.latex}
      </text>
    </g>
  );
}
