import React from 'react';

import type { TokenPath } from '../../../shared/types/tokenPath';
import { tokenPathPolyline } from '../../../shared/types/tokenPath';
import type { SceneNpcToken, SceneToken } from '../../../shared/types';
import { tokenPathKey, type TokenPathSessionState } from '../../../shared/types/tokenPathSession';

import styles from './TokenPathsOverlay.module.css';

type Viewport = { x: number; y: number; w: number; h: number };

type PathItem = {
  key: string;
  path: TokenPath;
  emphasized?: boolean;
};

type Props = {
  tokens: readonly SceneToken[];
  npcTokens?: readonly SceneNpcToken[];
  viewport: Viewport | null;
  /** control/editor: always; presentation: only presentationVisible */
  mode: 'always' | 'presentation';
  pathSession?: TokenPathSessionState | null;
  /** Highlight path currently edited */
  emphasizeKey?: string | null;
};

function toSvgPoints(path: TokenPath, viewport: Viewport): string {
  const pts = tokenPathPolyline(path);
  return pts
    .map((p) => {
      const x = viewport.x + p.nx * viewport.w;
      const y = viewport.y + p.ny * viewport.h;
      return `${x},${y}`;
    })
    .join(' ');
}

export function TokenPathsOverlay({
  tokens,
  npcTokens = [],
  viewport,
  mode,
  pathSession = null,
  emphasizeKey = null,
}: Props) {
  if (!viewport) return null;

  const items: PathItem[] = [];
  for (const t of tokens) {
    if (!t.path || t.path.points.length < 2) continue;
    const key = tokenPathKey('token', String(t.id));
    if (mode === 'presentation' && !pathSession?.presentationVisible[key]) continue;
    items.push({ key, path: t.path, emphasized: emphasizeKey === key });
  }
  for (const t of npcTokens) {
    if (!t.path || t.path.points.length < 2) continue;
    const key = tokenPathKey('npcToken', String(t.id));
    if (mode === 'presentation' && !pathSession?.presentationVisible[key]) continue;
    items.push({ key, path: t.path, emphasized: emphasizeKey === key });
  }
  if (items.length === 0) return null;

  return (
    <svg className={styles.layer} width="100%" height="100%" aria-hidden>
      {items.map((item) => {
        const pts = toSvgPoints(item.path, viewport);
        if (!pts) return null;
        const first = item.path.points[0]!;
        const fx = viewport.x + first.nx * viewport.w;
        const fy = viewport.y + first.ny * viewport.h;
        return (
          <g key={item.key} className={item.emphasized ? styles.emphasized : undefined}>
            <polyline className={styles.lineGlow} points={pts} fill="none" />
            <polyline className={styles.line} points={pts} fill="none" />
            <circle className={styles.start} cx={fx} cy={fy} r={4} />
            {item.path.closed ? (
              <circle
                className={styles.closed}
                cx={fx}
                cy={fy}
                r={7}
                fill="none"
              />
            ) : null}
          </g>
        );
      })}
    </svg>
  );
}
