"use client";

import type { ReactNode } from "react";
import { cn } from "@/lib/cn";
import { formatNumber } from "@/lib/format";
import type { Locale } from "@/i18n";

/**
 * Hand-rolled SVG chart primitives. The dashboard drew the line at charting
 * libraries on purpose — 14 data points don't need one — so these share the
 * coordinate math between the trend widgets and keep the charts direction-less
 * (always LTR) so Arabic stays readable.
 */

export const CHART_W = 1000;
export const CHART_H = 232;
export const CHART_PAD = { top: 16, right: 8, bottom: 28, left: 46 };

/** Smallest round "step × 10ⁿ" that clears the data, so bars never hit the top. */
export function niceCeil(value: number): number {
  if (value <= 0) return 4;
  const pow = 10 ** Math.floor(Math.log10(value));
  const norm = value / pow;
  const step = norm <= 1 ? 1 : norm <= 2 ? 2 : norm <= 4 ? 4 : norm <= 5 ? 5 : 10;
  return step * pow;
}

/** Y coordinate for a value on a chart of the given height. */
export function scaleY(value: number, max: number, height = CHART_H): number {
  const plotH = height - CHART_PAD.top - CHART_PAD.bottom;
  return CHART_PAD.top + plotH - (value / max) * plotH;
}

/** Y coordinate of the zero baseline. */
export function baselineY(height = CHART_H): number {
  return CHART_PAD.top + (height - CHART_PAD.top - CHART_PAD.bottom);
}

export interface AxisLabel {
  x: number;
  text: string;
}

/**
 * The axes a trend chart needs: horizontal gridlines with value labels on the
 * left plus date labels under the bottom edge. The series render as children.
 */
export function ChartFrame({
  height = CHART_H,
  max,
  yLabel,
  xLabels,
  label,
  children,
}: {
  height?: number;
  max: number;
  yLabel: (value: number) => string;
  xLabels: AxisLabel[];
  label: string;
  children: ReactNode;
}) {
  const ticks = Array.from({ length: 5 }, (_, i) => (max / 4) * i);

  return (
    <svg
      viewBox={`0 0 ${CHART_W} ${height}`}
      role="img"
      aria-label={label}
      className="w-full"
      style={{ direction: "ltr" }}
    >
      {ticks.map((tick) => {
        const y = scaleY(tick, max, height);
        return (
          <g key={tick}>
            <line
              x1={CHART_PAD.left}
              x2={CHART_W - CHART_PAD.right}
              y1={y}
              y2={y}
              stroke="currentColor"
              strokeOpacity={0.12}
              strokeWidth={1}
              className="text-muted"
            />
            <text
              x={CHART_PAD.left - 8}
              y={y}
              textAnchor="end"
              dominantBaseline="middle"
              fontSize={11}
              fill="currentColor"
              className="text-muted-foreground"
            >
              {yLabel(tick)}
            </text>
          </g>
        );
      })}
      {xLabels.map(({ x, text }, i) =>
        text ? (
          <text
            key={`${x}-${i}`}
            x={x}
            y={height - 8}
            textAnchor="middle"
            fontSize={11}
            fill="currentColor"
            className="text-muted-foreground"
          >
            {text}
          </text>
        ) : null,
      )}
      {children}
    </svg>
  );
}

/** Color key shown under the chart. */
export function ChartLegend({ items }: { items: { label: string; className: string }[] }) {
  return (
    <ul className="mt-3 flex flex-wrap items-center gap-x-4 gap-y-1.5">
      {items.map((item) => (
        <li key={item.label} className="flex items-center gap-1.5 text-xs text-muted-foreground">
          <span className={cn("h-2.5 w-2.5 rounded-sm", item.className)} aria-hidden />
          {item.label}
        </li>
      ))}
    </ul>
  );
}

/** Short "Sep 4" style date labels from the API's "Y-m-d" trend dates. */
export function formatChartDate(date: string, locale: Locale): string {
  const parsed = new Date(`${date}T00:00:00`);
  if (Number.isNaN(parsed.getTime())) return date;
  return new Intl.DateTimeFormat(locale === "ar" ? "ar-EG" : "en-US", {
    month: "short",
    day: "numeric",
  }).format(parsed);
}

/** Compact value label for chart axes (avoids wide currency symbols). */
export function compactAxisLabel(value: number, locale: Locale): string {
  if (value >= 1000) {
    return new Intl.NumberFormat(locale === "ar" ? "ar-EG" : "en-US", {
      notation: "compact",
      maximumFractionDigits: 1,
    }).format(value);
  }
  return formatNumber(value, locale);
}