/**
 * Shared utilities and sub-components for all shadcn chart components.
 * Not part of the public package API — internal use only.
 */
import React from "react";
import { Button } from "./button";

// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------

export type ChartPeriod = 1 | 3 | 6 | 12;
export type ChartGranularity = "monthly" | "daily";

// ---------------------------------------------------------------------------
// Period / slice config
// ---------------------------------------------------------------------------

/**
 * How many data points to slice per period × granularity combination.
 * monthly: slice by calendar month count.
 * daily:   slice by approximate day count (1M=30d, 3M=90d, 6M=180d, 12M=365d).
 */
export const CHART_SLICE_COUNT: Record<
  ChartGranularity,
  Record<ChartPeriod, number>
> = {
  monthly: { 1: 1, 3: 3, 6: 6, 12: 12 },
  daily: { 1: 30, 3: 90, 6: 180, 12: 365 },
};

/** Period buttons shown per granularity. monthly hides 1M; daily shows all four. */
export const CHART_PERIODS: Record<ChartGranularity, ChartPeriod[]> = {
  monthly: [3, 6, 12],
  daily: [1, 3, 6, 12],
};

// ---------------------------------------------------------------------------
// Chart.js helpers
// ---------------------------------------------------------------------------

export function hexToRgba(hex: string, alpha: number): string {
  const clean = hex.replace("#", "");
  const full =
    clean.length === 3
      ? clean
          .split("")
          .map((c) => c + c)
          .join("")
      : clean;
  const r = parseInt(full.slice(0, 2), 16);
  const g = parseInt(full.slice(2, 4), 16);
  const b = parseInt(full.slice(4, 6), 16);
  return `rgba(${r},${g},${b},${alpha})`;
}

/** Opacity steps to derive distinct shades from a single brand color (up to 6 datasets). */
export const DATASET_ALPHAS = [1, 0.72, 0.52, 0.36, 0.24, 0.15];

// ---------------------------------------------------------------------------
// Fallback resolved colors for Chart.js canvas API.
// Chart.js requires actual hex/rgb strings — CSS variables cannot be used directly.
// All values match the :root defaults defined in globals.css.
// ---------------------------------------------------------------------------

/** Fallback for --primary (WealthX green) */
export const FALLBACK_PRIMARY = "#33FF99";
/** Fallback for --brand-secondary (WealthX dark navy) */
export const FALLBACK_SECONDARY = "#162029";
/** Fallback for --background (white) */
export const FALLBACK_BG = "#ffffff";
/** Fallback for --foreground (near-black) */
export const FALLBACK_FOREGROUND = "#040D13";
/** Fallback for --muted-foreground used as axis tick color */
export const FALLBACK_TICK = "#9EAAB5";
/** Fallback neutral grey for comparison / suburb lines */
export const FALLBACK_NEUTRAL = "#B9BCBF";
/** Fallback semi-transparent grid line color */
export const FALLBACK_GRID_COLOR = "rgba(0,0,0,0.06)";

/**
 * Semantic severity colors for alert / status charts.
 * Match WealthX design tokens: --destructive, --warning, --success.
 * Intentionally fixed — severity meaning must be recognisable regardless of tenant theme.
 */
export const SEVERITY_COLORS = {
  high: "#F44336", // default --destructive  oklch(0.643 0.215 28.8)
  medium: "#FF9800", // default --warning     oklch(0.77  0.174  64.1)
  low: "#4CAF50", // default --success        oklch(0.673 0.162 144.2)
} as const;

/**
 * Re-export abbreviated currency formatter from shared lib.
 * Kept as `formatAbbrev` for backward compatibility with existing chart consumers.
 */
import { formatCurrencyAbbrev as formatAbbrev } from "@/lib/format-currency";
export { formatAbbrev };

// ---------------------------------------------------------------------------
// Chart date label — "Jan 15" for x-axis tick labels (daily charts)
// ---------------------------------------------------------------------------

/** Format an ISO date string as "Jan 15" for daily-chart x-axis labels. */
export function formatChartDateLabel(iso: string): string {
  const d = new Date(iso);
  return d.toLocaleDateString("en-US", { month: "short", day: "numeric" });
}

// ---------------------------------------------------------------------------
// Tooltip date format
// ---------------------------------------------------------------------------

/**
 * Format an ISO date string for the chart tooltip title.
 * Daily granularity includes the day; monthly shows only month + year.
 */
export function formatTooltipDate(
  iso: string,
  granularity: ChartGranularity,
): string {
  const d = new Date(iso);
  return d.toLocaleDateString(
    "en-US",
    granularity === "daily"
      ? { month: "short", day: "numeric", year: "numeric" }
      : { month: "short", year: "numeric" },
  );
}

// ---------------------------------------------------------------------------
// Date / count formatters (shared across bar and doughnut charts)
// ---------------------------------------------------------------------------

/** Format an ISO date string as "Mon 'YY" for X-axis month labels. */
export function formatMonthLabel(iso: string): string {
  return new Date(iso).toLocaleDateString("en-US", {
    month: "short",
    year: "2-digit",
  });
}

/** Format a raw integer count for axis ticks and tooltips. */
export function formatCount(n: number): string {
  if (n >= 1_000) return `${(n / 1_000).toFixed(1)}k`;
  return String(Math.round(n));
}

// ---------------------------------------------------------------------------
// Sub-components
// ---------------------------------------------------------------------------

export function ChartLegendItem({
  label,
  color,
  lineStyle,
}: {
  label: string;
  color: string;
  /** When provided, renders a line indicator instead of a square swatch */
  lineStyle?: "solid" | "dashed";
}) {
  return (
    <div className="flex items-center gap-1.5">
      {lineStyle ? (
        <svg
          width="20"
          height="10"
          viewBox="0 0 20 10"
          aria-hidden="true"
          style={{ flexShrink: 0 }}
        >
          <line
            x1="0"
            y1="5"
            x2="20"
            y2="5"
            stroke={color}
            strokeWidth="2"
            strokeLinecap="square"
            strokeDasharray={lineStyle === "dashed" ? "5 3" : undefined}
          />
        </svg>
      ) : (
        <div
          style={{
            width: 10,
            height: 10,
            backgroundColor: color,
            flexShrink: 0,
          }}
        />
      )}
      <span className="text-sm text-muted-foreground leading-none">
        {label}
      </span>
    </div>
  );
}

/**
 * One row in a doughnut chart legend — circle swatch, label, dollar value, percent.
 * The label truncates when the container is constrained.
 */
export function DoughnutLegendRow({
  label,
  color,
  value,
  percent,
}: {
  label: string;
  color: string;
  value: number;
  percent: string;
}) {
  return (
    <div className="flex items-center justify-between gap-2">
      <div className="flex items-center gap-1.5 min-w-0">
        <div
          style={{
            width: 10,
            height: 10,
            borderRadius: "50%",
            backgroundColor: color,
            flexShrink: 0,
          }}
        />
        <span className="text-sm text-muted-foreground leading-none truncate">
          {label}
        </span>
      </div>
      <div className="flex items-center gap-2 shrink-0">
        <span className="text-sm font-medium leading-none">
          {formatAbbrev(value)}
        </span>
        <span className="text-sm text-muted-foreground leading-none w-12 text-right">
          {percent}
        </span>
      </div>
    </div>
  );
}

export function ChartPeriodButton({
  period,
  active,
  onClick,
  unit = "M",
}: {
  period: number;
  active: boolean;
  onClick: () => void;
  unit?: string;
}) {
  return (
    <Button
      variant={active ? "default" : "outline"}
      size="xs"
      onClick={onClick}
    >
      {period}
      {unit}
    </Button>
  );
}
