import type {
  AdminDatasetPoint,
  AdminDatasetResult,
  AdminDatasetSummary,
} from "@xtablo/shared-types";

type ChartBuilderProps = {
  dataset: AdminDatasetResult | null;
  datasets: AdminDatasetSummary[];
  onSelectDatasetId: (datasetId: string) => void;
  selectedDatasetId: string | null;
};

function BarChart({ points }: { points: AdminDatasetPoint[] }) {
  const maxValue = Math.max(...points.map((point) => point.value), 1);

  return (
    <div className="grid min-h-64 grid-cols-[repeat(auto-fit,minmax(56px,1fr))] items-end gap-3">
      {points.map((point) => (
        <div className="flex h-full flex-col justify-end gap-2" key={point.label}>
          <div
            className="rounded-t-2xl bg-[linear-gradient(180deg,rgba(20,36,84,0.92),rgba(88,140,126,0.9))]"
            style={{ height: `${Math.max((point.value / maxValue) * 180, 12)}px` }}
          />
          <div>
            <p className="text-xs font-medium">{point.value}</p>
            <p className="truncate text-[11px] uppercase tracking-[0.16em] text-foreground/55">
              {point.label}
            </p>
          </div>
        </div>
      ))}
    </div>
  );
}

function LineChart({ points }: { points: AdminDatasetPoint[] }) {
  const width = 560;
  const height = 220;
  const maxValue = Math.max(...points.map((point) => point.value), 1);
  const polyline = points
    .map((point, index) => {
      const x = points.length === 1 ? width / 2 : (index / (points.length - 1)) * width;
      const y = height - (point.value / maxValue) * (height - 24) - 12;
      return `${x},${y}`;
    })
    .join(" ");

  return (
    <div className="space-y-4">
      <svg
        className="w-full overflow-visible rounded-[2rem] border border-border bg-[linear-gradient(180deg,rgba(252,249,244,0.96),rgba(239,235,225,0.96))] p-4"
        viewBox={`0 0 ${width} ${height}`}
      >
        <polyline
          fill="none"
          points={polyline}
          stroke="rgb(23 37 84)"
          strokeLinecap="round"
          strokeLinejoin="round"
          strokeWidth="4"
        />
        {points.map((point, index) => {
          const x = points.length === 1 ? width / 2 : (index / (points.length - 1)) * width;
          const y = height - (point.value / maxValue) * (height - 24) - 12;

          return <circle cx={x} cy={y} fill="rgb(15 118 110)" key={point.label} r="5" />;
        })}
      </svg>
      <div className="grid gap-3 md:grid-cols-3">
        {points.map((point) => (
          <div
            className="rounded-2xl border border-border/80 bg-background/70 px-3 py-2"
            key={point.label}
          >
            <p className="text-xs uppercase tracking-[0.18em] text-foreground/50">{point.label}</p>
            <p className="mt-1 text-lg font-semibold">{point.value}</p>
          </div>
        ))}
      </div>
    </div>
  );
}

function DonutChart({ points }: { points: AdminDatasetPoint[] }) {
  const total = points.reduce((sum, point) => sum + point.value, 0) || 1;
  const palette = ["#172554", "#0f766e", "#b45309", "#7c2d12", "#475569"];
  let currentStop = 0;
  const gradientStops = points
    .map((point, index) => {
      const start = currentStop;
      currentStop += (point.value / total) * 100;
      return `${palette[index % palette.length]} ${start}% ${currentStop}%`;
    })
    .join(", ");

  return (
    <div className="grid gap-6 md:grid-cols-[220px_minmax(0,1fr)] md:items-center">
      <div
        className="mx-auto h-52 w-52 rounded-full border border-border"
        style={{
          background: `conic-gradient(${gradientStops})`,
        }}
      >
        <div className="m-auto mt-8 flex h-36 w-36 items-center justify-center rounded-full bg-card text-center">
          <div>
            <p className="text-xs uppercase tracking-[0.18em] text-foreground/50">Total</p>
            <p className="mt-1 text-3xl font-semibold">{total}</p>
          </div>
        </div>
      </div>
      <div className="space-y-3">
        {points.map((point, index) => (
          <div
            className="flex items-center justify-between rounded-2xl border border-border/80 px-4 py-3"
            key={point.label}
          >
            <div className="flex items-center gap-3">
              <span
                className="h-3 w-3 rounded-full"
                style={{ backgroundColor: palette[index % palette.length] }}
              />
              <p className="text-sm font-medium">{point.label}</p>
            </div>
            <p className="text-sm text-foreground/70">{point.value}</p>
          </div>
        ))}
      </div>
    </div>
  );
}

export function ChartBuilder({
  dataset,
  datasets,
  onSelectDatasetId,
  selectedDatasetId,
}: ChartBuilderProps) {
  return (
    <div className="space-y-6">
      <div className="flex flex-wrap gap-3">
        {datasets.map((entry) => (
          <button
            className={`rounded-full border px-4 py-2 text-sm ${
              entry.id === selectedDatasetId
                ? "border-foreground bg-foreground text-background"
                : "border-border bg-card"
            }`}
            key={entry.id}
            onClick={() => onSelectDatasetId(entry.id)}
            type="button"
          >
            {entry.label}
          </button>
        ))}
      </div>

      {dataset ? (
        <section className="rounded-[2rem] border border-border bg-card p-6 shadow-[0_24px_80px_rgba(15,23,42,0.08)]">
          <div className="mb-6 flex flex-wrap items-end justify-between gap-4">
            <div>
              <p className="text-xs uppercase tracking-[0.2em] text-foreground/50">Dataset</p>
              <h2 className="mt-2 text-3xl font-semibold">{dataset.label}</h2>
              <p className="mt-2 max-w-2xl text-sm text-foreground/70">{dataset.description}</p>
            </div>
            <div className="rounded-2xl border border-border/80 bg-background/70 px-4 py-3 text-right">
              <p className="text-xs uppercase tracking-[0.18em] text-foreground/50">
                {dataset.dimensionLabel} x {dataset.metricLabel}
              </p>
              <p className="mt-2 text-lg font-semibold">
                {dataset.points.reduce((sum, point) => sum + point.value, 0)}
              </p>
            </div>
          </div>

          {dataset.chartType === "line" ? <LineChart points={dataset.points} /> : null}
          {dataset.chartType === "bar" ? <BarChart points={dataset.points} /> : null}
          {dataset.chartType === "donut" ? <DonutChart points={dataset.points} /> : null}
        </section>
      ) : null}
    </div>
  );
}
