import * as React from "react";
import Link from "next/link";
import { ArrowDownRight, ArrowUpRight, Minus, type LucideIcon } from "lucide-react";
import { cn } from "@/lib/utils";
import { Tooltip } from "./primitives";
import { AnimatedText } from "@/components/motion/animated-number";

export function Sparkline({ data, className, tone = "primary", height = 28 }: { data: number[]; className?: string; tone?: "primary" | "positive" | "negative" | "muted"; height?: number }) {
  const id = React.useId();
  if (!data.length) return null;
  const w = 80;
  const max = Math.max(...data, 1);
  const min = Math.min(...data, 0);
  const range = max - min || 1;
  const step = w / Math.max(data.length - 1, 1);
  const pts = data.map((v, i) => [i * step, height - ((v - min) / range) * (height - 4) - 2] as const);
  const d = pts.map(([x, y], i) => `${i === 0 ? "M" : "L"}${x.toFixed(1)},${y.toFixed(1)}`).join(" ");
  const area = `${d} L${w},${height} L0,${height} Z`;
  const color = { primary: "var(--color-primary)", positive: "var(--color-positive-500)", negative: "var(--color-negative-500)", muted: "var(--color-stone-400)" }[tone];
  return (
    <svg viewBox={`0 0 ${w} ${height}`} className={cn("h-7 w-20", className)} preserveAspectRatio="none" aria-hidden>
      <defs>
        <linearGradient id={id} x1="0" x2="0" y1="0" y2="1">
          <stop offset="0%" stopColor={color} stopOpacity="0.3" />
          <stop offset="100%" stopColor={color} stopOpacity="0" />
        </linearGradient>
      </defs>
      <path d={area} fill={`url(#${id})`} />
      <path d={d} pathLength={1} className="spark-line" fill="none" stroke={color} strokeWidth="1.75" strokeLinejoin="round" strokeLinecap="round" vectorEffect="non-scaling-stroke" />
    </svg>
  );
}

export interface KpiCardProps {
  label: string;
  value: React.ReactNode;
  sub?: React.ReactNode;
  delta?: number | null;
  deltaLabel?: string;
  /** whether an increase is good (revenue) or bad (cancellations) */
  invert?: boolean;
  icon?: LucideIcon;
  spark?: number[];
  href?: string;
  tone?: "default" | "brand" | "positive" | "warning" | "negative" | "info";
  hint?: string;
  className?: string;
  compact?: boolean;
}

const TONES = {
  default: { icon: "bg-surface-2 text-fg-muted", wash: "" },
  brand: { icon: "bg-primary/12 text-primary", wash: "from-primary/[0.07]" },
  positive: { icon: "bg-positive-500/12 text-positive-600", wash: "from-positive-500/[0.07]" },
  warning: { icon: "bg-warning-500/12 text-warning-600", wash: "from-warning-500/[0.08]" },
  negative: { icon: "bg-negative-500/12 text-negative-600", wash: "from-negative-500/[0.07]" },
  info: { icon: "bg-info-500/12 text-info-600", wash: "from-info-500/[0.07]" },
};

/**
 * KPI tile: eyebrow label, big tabular number, delta pill and an optional
 * sparkline. Tinted tones paint a soft top-right wash so the eye lands on the
 * important numbers first.
 */
export function KpiCard({ label, value, sub, delta, deltaLabel = "vs previous period", invert, icon: Icon, spark, href, tone = "default", hint, className, compact }: KpiCardProps) {
  const good = delta == null ? null : invert ? delta < 0 : delta > 0;
  const neutral = delta === 0 || delta == null;
  const t = TONES[tone];

  const body = (
    <div className={cn("group relative flex h-full flex-col justify-between overflow-hidden rounded-xl border border-border bg-surface shadow-xs hairline-top transition-all", href && "card-lift", compact ? "p-3.5" : "p-4 sm:p-5", className)}>
      {t.wash ? <div className={cn("pointer-events-none absolute inset-0 bg-gradient-to-bl to-transparent", t.wash)} aria-hidden /> : null}
      <div className="relative flex items-start justify-between gap-2">
        <div className="flex min-w-0 items-center gap-1.5">
          <p className="eyebrow line-clamp-2 leading-tight">{label}</p>
          {hint ? (
            <Tooltip content={hint}>
              <span className="inline-flex size-3.5 shrink-0 cursor-help items-center justify-center rounded-full border border-border-strong text-[9px] font-bold text-fg-subtle">?</span>
            </Tooltip>
          ) : null}
        </div>
        {Icon ? (
          <span className={cn("flex shrink-0 items-center justify-center rounded-lg", compact ? "size-7 [&_svg]:size-3.5" : "size-9 [&_svg]:size-4", t.icon)}>
            <Icon strokeWidth={1.75} />
          </span>
        ) : null}
      </div>
      <div className={cn("relative flex items-end justify-between gap-3", compact ? "mt-2" : "mt-3")}>
        <div className="min-w-0">
          <p className={cn("break-words font-semibold leading-none tracking-tight text-fg tabular", compact ? "text-lg sm:text-xl" : "text-[22px] sm:text-[26px]")}>
            <AnimatedText text={value} />
          </p>
          {sub || delta != null ? (
            <div className="mt-2 flex flex-wrap items-center gap-x-2 gap-y-0.5 text-xs">
              {delta != null ? (
                <span className={cn("inline-flex items-center gap-0.5 rounded-full px-1.5 py-0.5 font-medium tabular", neutral ? "bg-surface-2 text-fg-muted" : good ? "bg-positive-500/10 text-positive-600" : "bg-negative-500/10 text-negative-600")}>
                  {neutral ? <Minus className="size-3" /> : delta > 0 ? <ArrowUpRight className="size-3" /> : <ArrowDownRight className="size-3" />}
                  {Math.abs(delta).toFixed(1)}%
                </span>
              ) : null}
              {sub ? <span className="truncate text-fg-subtle">{sub}</span> : delta != null ? <span className="truncate text-fg-subtle">{deltaLabel}</span> : null}
            </div>
          ) : null}
        </div>
        {spark && spark.length > 1 ? <Sparkline data={spark} tone={good === null ? "primary" : good ? "positive" : "negative"} className="hidden shrink-0 transition-transform duration-300 group-hover:scale-105 sm:block" /> : null}
      </div>
    </div>
  );
  return href ? (
    <Link href={href} className="block h-full rounded-xl focus:outline-none focus-visible:ring-2 focus-visible:ring-ring">
      {body}
    </Link>
  ) : (
    body
  );
}

/** Compact inline stat for mobile summaries. */
export function Stat({ label, value, className, tone }: { label: string; value: React.ReactNode; className?: string; tone?: "positive" | "warning" | "negative" | "muted" }) {
  return (
    <div className={cn("flex flex-col gap-0.5", className)}>
      <span className="eyebrow">{label}</span>
      <span className={cn("text-base font-semibold tabular text-fg", tone === "positive" && "text-positive-600", tone === "warning" && "text-warning-600", tone === "negative" && "text-negative-600", tone === "muted" && "text-fg-muted")}>{value}</span>
    </div>
  );
}
