"use client";

import { motion } from "motion/react";
import { ChartFrame } from "./chart-frame";
import { linearScale, niceTicks, linePath, smoothPath, areaPath, catColor, type Point } from "@/lib/chart-utils";

export type AreaSeries = { label: string; data: Point[] };

type AreaChartProps = {
  series: AreaSeries[];
  xLabels?: string[];
  smooth?: boolean;
  yMax?: number;
  width?: number;
  height?: number;
  className?: string;
};

const M = { top: 16, right: 18, bottom: 34, left: 44 };

/**
 * AreaChart — filled areas revealed by a bottom-up clip wipe (scaleY origin
 * bottom), with the line drawn on top. Stacked series cascade by index.
 */
export function AreaChart({
  series,
  xLabels,
  smooth = false,
  yMax,
  width = 640,
  height = 380,
  className,
}: AreaChartProps) {
  const all = series.flatMap((s) => s.data);
  const xs = all.map((p) => p.x);
  const ys = all.map((p) => p.y);
  const xDomain: [number, number] = [Math.min(...xs), Math.max(...xs)];
  const yDomain: [number, number] = [Math.min(0, ...ys), yMax ?? Math.max(...ys)];
  const sx = linearScale(xDomain, [M.left, width - M.right]);
  const sy = linearScale(yDomain, [height - M.bottom, M.top]);
  const baseY = height - M.bottom;
  const ticks = niceTicks(yDomain[0], yDomain[1], 4);

  return (
    <ChartFrame width={width} height={height} label="Gráfica de áreas" className={className}>
      {({ inView }) => (
        <>
          {ticks.map((t) => (
            <g key={t}>
              <line x1={M.left} x2={width - M.right} y1={sy(t)} y2={sy(t)} stroke="var(--ink-100)" strokeWidth={1} />
              <text x={M.left - 8} y={sy(t)} textAnchor="end" dominantBaseline="middle" fontSize={11} fill="var(--ink-400)">
                {t}
              </text>
            </g>
          ))}
          {xLabels?.map((lab, i) => (
            <text key={i} x={sx(i)} y={height - M.bottom + 18} textAnchor="middle" fontSize={11} fill="var(--ink-500)">
              {lab}
            </text>
          ))}
          {series.map((s, si) => {
            const pts = s.data.map((p) => ({ x: sx(p.x), y: sy(p.y) }));
            const fill = catColor(si);
            const a = areaPath(pts, baseY, smooth);
            const d = smooth ? smoothPath(pts) : linePath(pts);
            const clipId = `area-clip-${si}-${Math.round(pts[0]?.x ?? 0)}`;
            return (
              <g key={s.label}>
                <defs>
                  <clipPath id={clipId} clipPathUnits="userSpaceOnUse">
                    <motion.rect
                      x={0}
                      width={width}
                      y={M.top}
                      height={baseY - M.top}
                      initial={{ scaleY: 0 }}
                      animate={inView ? { scaleY: 1 } : { scaleY: 0 }}
                      transition={{ duration: 0.7, delay: 0.15 + si * 0.18, ease: [0.22, 1, 0.36, 1] }}
                      style={{ transformOrigin: `0px ${baseY}px` }}
                    />
                  </clipPath>
                </defs>
                <path d={a} fill={fill} fillOpacity={0.18} clipPath={`url(#${clipId})`} />
                <motion.path
                  d={d}
                  fill="none"
                  stroke={fill}
                  strokeWidth={2.5}
                  strokeLinecap="round"
                  strokeLinejoin="round"
                  initial={{ pathLength: 0 }}
                  animate={inView ? { pathLength: 1 } : { pathLength: 0 }}
                  transition={{ duration: 1, delay: 0.15 + si * 0.18, ease: [0.22, 1, 0.36, 1] }}
                />
              </g>
            );
          })}
        </>
      )}
    </ChartFrame>
  );
}
