"use client";

import { motion } from "motion/react";
import { ChartFrame } from "@/components/charts/chart-frame";

export type Entity = { id: string; title: string; fields: string[]; x: number; y: number; w?: number };
export type Relation = { from: string; to: string; label?: string };

type ERDiagramProps = {
  entities: Entity[];
  relations: Relation[];
  width?: number;
  height?: number;
  className?: string;
};

const ROW_H = 24;
const HEAD_H = 30;

/** ERDiagram — entity cards (title + field rows) reveal; relations draw between card centers with a cardinality label. */
export function ERDiagram({ entities, relations, width = 720, height = 420, className }: ERDiagramProps) {
  const byId = new Map(entities.map((e) => [e.id, e]));
  const dims = (e: Entity) => ({ w: e.w ?? 160, h: HEAD_H + e.fields.length * ROW_H });
  const center = (e: Entity) => {
    const { w, h } = dims(e);
    return { x: e.x + w / 2, y: e.y + h / 2 };
  };

  return (
    <ChartFrame width={width} height={height} label="Diagrama entidad-relación" className={className}>
      {({ inView, reduce }) => (
        <>
          {relations.map((r, i) => {
            const a = byId.get(r.from);
            const b = byId.get(r.to);
            if (!a || !b) return null;
            const ca = center(a);
            const cb = center(b);
            return (
              <g key={i}>
                <motion.line
                  x1={ca.x} y1={ca.y} x2={cb.x} y2={cb.y}
                  stroke="var(--ink-400)" strokeWidth={1.5}
                  initial={reduce ? false : { pathLength: 0, opacity: 0 }}
                  animate={inView ? { pathLength: 1, opacity: 1 } : { pathLength: 0, opacity: 0 }}
                  transition={{ duration: 0.6, delay: 0.4 + i * 0.1, ease: [0.22, 1, 0.36, 1] }}
                />
                {r.label && (
                  <motion.text
                    x={(ca.x + cb.x) / 2} y={(ca.y + cb.y) / 2 - 6}
                    textAnchor="middle" fontSize={11} fontWeight={700} fill="var(--accent-700)"
                    initial={{ opacity: 0 }} animate={inView ? { opacity: 1 } : { opacity: 0 }}
                    transition={{ duration: 0.3, delay: 0.4 + i * 0.1 + 0.5 }}
                  >
                    {r.label}
                  </motion.text>
                )}
              </g>
            );
          })}
          {entities.map((e, i) => {
            const { w, h } = dims(e);
            return (
              <motion.g
                key={e.id}
                initial={reduce ? false : { opacity: 0, y: 10 }}
                animate={inView ? { opacity: 1, y: 0 } : { opacity: 0, y: 10 }}
                transition={{ duration: 0.4, delay: 0.1 + i * 0.12, ease: [0.22, 1, 0.36, 1] }}
              >
                <rect x={e.x} y={e.y} width={w} height={h} rx={6} fill="var(--paper)" stroke="var(--ink-200)" strokeWidth={1} />
                <rect x={e.x} y={e.y} width={w} height={HEAD_H} rx={6} fill="var(--ink-900)" />
                <rect x={e.x} y={e.y + HEAD_H - 6} width={w} height={6} fill="var(--ink-900)" />
                <text x={e.x + w / 2} y={e.y + HEAD_H / 2} textAnchor="middle" dominantBaseline="middle" fontSize={12} fontWeight={800} fill="var(--accent-500)">
                  {e.title}
                </text>
                {e.fields.map((f, fi) => (
                  <text key={fi} x={e.x + 12} y={e.y + HEAD_H + ROW_H * (fi + 0.5)} dominantBaseline="middle" fontSize={11} fill="var(--ink-700)">
                    {f}
                  </text>
                ))}
              </motion.g>
            );
          })}
        </>
      )}
    </ChartFrame>
  );
}
