import React, { useMemo, useState } from "react";
import { chartScaleMax } from "../../utils/documentCreationTrend.js";

const WIDTH = 640;
const HEIGHT = 280;
const PAD = { top: 20, right: 24, bottom: 44, left: 48 };

function buildPoints(data, yMax) {
  const plotW = WIDTH - PAD.left - PAD.right;
  const plotH = HEIGHT - PAD.top - PAD.bottom;
  const lastIndex = Math.max(data.length - 1, 1);

  return data.map((row, index) => {
    const count = Number(row.count) || 0;
    const x = PAD.left + (index / lastIndex) * plotW;
    const y = PAD.top + plotH - (yMax > 0 ? (count / yMax) * plotH : 0);
    return { ...row, count, x, y };
  });
}

function linePath(points) {
  if (!points.length) return "";
  return points.map((p, i) => `${i === 0 ? "M" : "L"} ${p.x} ${p.y}`).join(" ");
}

function areaPath(points) {
  if (!points.length) return "";
  const baseY = HEIGHT - PAD.bottom;
  let d = `M ${points[0].x} ${baseY} L ${points[0].x} ${points[0].y}`;
  for (let i = 1; i < points.length; i += 1) {
    d += ` L ${points[i].x} ${points[i].y}`;
  }
  d += ` L ${points[points.length - 1].x} ${baseY} Z`;
  return d;
}

/**
 * @param {{
 *   data: Array<{ period: string, label: string, count: number }>,
 *   loading?: boolean,
 * }} props
 */
export default function DocumentCreationTrendChart({ data = [], loading = false }) {
  const [activeIndex, setActiveIndex] = useState(null);

  const maxCount = useMemo(
    () => Math.max(0, ...data.map((row) => Number(row.count) || 0)),
    [data]
  );

  const yMax = useMemo(() => chartScaleMax(maxCount), [maxCount]);

  const yTicks = useMemo(() => {
    const steps = 4;
    return Array.from({ length: steps + 1 }, (_, i) =>
      Math.round((yMax * (steps - i)) / steps)
    );
  }, [yMax]);

  const points = useMemo(() => buildPoints(data, yMax), [data, yMax]);
  const plotH = HEIGHT - PAD.top - PAD.bottom;
  const totalCreated = useMemo(
    () => data.reduce((sum, row) => sum + (Number(row.count) || 0), 0),
    [data]
  );

  const activePoint =
    activeIndex != null && points[activeIndex] ? points[activeIndex] : null;

  if (loading) {
    return (
      <div className="swi-admin-trend swi-panel">
        <p className="swi-muted">Loading creation trend…</p>
      </div>
    );
  }

  return (
    <div className="swi-admin-trend swi-panel">
      <header className="swi-admin-trend__head">
        <div>
          <h2 className="swi-admin-trend__title">SWI creation trend</h2>
          <p className="swi-admin-trend__desc">
            Monthly documents registered (by issue date).
          </p>
        </div>
        <div className="swi-admin-trend__metric" aria-live="polite">
          {activePoint ? (
            <>
              <strong>{activePoint.count}</strong>
              <span>{activePoint.label}</span>
            </>
          ) : (
            <>
              <strong>{totalCreated}</strong>
              <span>Last 12 months</span>
            </>
          )}
        </div>
      </header>

      {!data.length ? (
        <p className="swi-muted">No document creation data for this period.</p>
      ) : (
        <div className="swi-admin-trend__canvas-wrap">
          <svg
            className="swi-admin-trend__svg"
            viewBox={`0 0 ${WIDTH} ${HEIGHT}`}
            role="img"
            aria-label="Line chart of SWI documents created per month"
          >
            <defs>
              <linearGradient id="swi-trend-area" x1="0" y1="0" x2="0" y2="1">
                <stop offset="0%" stopColor="var(--swi-accent)" stopOpacity="0.28" />
                <stop offset="100%" stopColor="var(--swi-accent)" stopOpacity="0.02" />
              </linearGradient>
            </defs>

            {yTicks.map((tick) => {
              const y =
                PAD.top + plotH - (yMax > 0 ? (tick / yMax) * plotH : 0);
              return (
                <g key={tick}>
                  <line
                    x1={PAD.left}
                    y1={y}
                    x2={WIDTH - PAD.right}
                    y2={y}
                    className="swi-admin-trend__grid-line"
                  />
                  <text
                    x={PAD.left - 10}
                    y={y}
                    className="swi-admin-trend__y-label"
                    textAnchor="end"
                    dominantBaseline="middle"
                  >
                    {tick}
                  </text>
                </g>
              );
            })}

            <line
              x1={PAD.left}
              y1={HEIGHT - PAD.bottom}
              x2={WIDTH - PAD.right}
              y2={HEIGHT - PAD.bottom}
              className="swi-admin-trend__axis-line"
            />

            <path d={areaPath(points)} className="swi-admin-trend__area" />
            <path d={linePath(points)} className="swi-admin-trend__line" />

            {points.map((point, index) => {
              const showLabel =
                data.length <= 6 ||
                index === 0 ||
                index === data.length - 1 ||
                index % 2 === 0;
              return (
                <g key={point.period}>
                  <circle
                    cx={point.x}
                    cy={point.y}
                    r={activeIndex === index ? 6 : 4.5}
                    className={`swi-admin-trend__dot${activeIndex === index ? " is-active" : ""}`}
                    onMouseEnter={() => setActiveIndex(index)}
                    onMouseLeave={() => setActiveIndex(null)}
                    onFocus={() => setActiveIndex(index)}
                    onBlur={() => setActiveIndex(null)}
                    tabIndex={0}
                    role="presentation"
                  >
                    <title>{`${point.label}: ${point.count} document${point.count === 1 ? "" : "s"}`}</title>
                  </circle>
                  {showLabel ? (
                    <text
                      x={point.x}
                      y={HEIGHT - 14}
                      className="swi-admin-trend__x-label"
                      textAnchor="middle"
                    >
                      {point.label}
                    </text>
                  ) : null}
                </g>
              );
            })}
          </svg>
        </div>
      )}
    </div>
  );
}
