import { format } from "date-fns";
import type { GraphDataset } from "../../types/medical";

type TooltipPayloadItem = {
  dataKey?: string;
  name?: string;
  value?: unknown;
  payload?: Record<string, unknown>;
};

export const MedicationShape = (props: any) => {
  const { x, width, fill, name } = props;
  const barHeight = 24;
  const yPos = 10;

  if (x === undefined || width === undefined || width < 2) return null;

  const maxLabelWidth = width - 14;
  const estimatedCharWidth = 6.2;
  const maxChars = Math.floor(maxLabelWidth / estimatedCharWidth);
  const label =
    maxChars > 3 && typeof name === "string"
      ? name.length > maxChars
        ? `${name.slice(0, maxChars - 3)}...`
        : name
      : "";

  return (
    <g pointerEvents="none">
      <rect
        x={x}
        y={yPos}
        width={width}
        height={barHeight}
        rx={12}
        fill={fill}
        fillOpacity={0.8}
        stroke="none"
      />
      {width > 40 && label && (
        <text
          x={x + width / 2}
          y={yPos + 16}
          textAnchor="middle"
          fill="white"
          fontSize={11}
          fontWeight="600"
          className="pointer-events-none select-none"
        >
          {label}
        </text>
      )}
    </g>
  );
};

export const getLastNonNullIndex = (data: Record<string, unknown>[], dataKey: string): number => {
  for (let index = data.length - 1; index >= 0; index -= 1) {
    const value = data[index]?.[dataKey];
    if (value !== null && value !== undefined) return index;
  }

  return -1;
};

export const createPointRenderer = (
  pointStyle: GraphDataset["pointStyle"],
  color: string,
  isActive: boolean = false
) => {
  if (pointStyle === "none") return false;

  const size = isActive ? 10 : 6;
  const radius = size / 2;

  return (props: any) => {
    const { cx, cy, value, payload, dataKey } = props;
    const pointValue = payload && dataKey ? payload[dataKey] : value;

    if (pointValue === null || pointValue === undefined || Number.isNaN(pointValue)) {
      return <></>;
    }

    if (cx === undefined || cy === undefined) {
      return <></>;
    }

    if (pointStyle === "square") {
      return (
        <rect
          x={cx - radius}
          y={cy - radius}
          width={size}
          height={size}
          fill={color}
          stroke="white"
          strokeWidth={isActive ? 2 : 1}
        />
      );
    }

    return (
      <circle
        cx={cx}
        cy={cy}
        r={radius}
        fill={color}
        stroke="white"
        strokeWidth={isActive ? 2 : 1}
      />
    );
  };
};

export const createOutOfRangeIndicatorDot = (props: any) => {
  const { cx, cy, value } = props;

  if (value === null || value === undefined || Number.isNaN(value)) {
    return <></>;
  }

  if (cx === undefined || cy === undefined) {
    return <></>;
  }

  return (
    <circle
      cx={cx}
      cy={cy}
      r={5.5}
      fill="none"
      stroke="#ef4444"
      strokeWidth={1.75}
      strokeDasharray="2 2"
    />
  );
};

export const createChartTooltip = (
  datasets: GraphDataset[],
  normalizeByReference: boolean
) =>
  ({ active, label, payload }: any) => {
    if (!active || !payload?.length) return null;

    const rows = (payload as TooltipPayloadItem[])
      .map((item) => {
        const dataKey = String(item?.dataKey ?? "");
        if (
          dataKey === "_dummy" ||
          dataKey.endsWith("__refMin") ||
          dataKey.endsWith("__refMax") ||
          dataKey.endsWith("__outOfRangeIndicator")
        ) {
          return null;
        }

        const ds = datasets.find((dataset) => dataset.id === dataKey || dataset.name === item?.name || dataset.id === item?.name);
        if (!ds || ds.type === "medication") return null;

        const isNormalized = normalizeByReference && ds.refMin !== undefined && ds.refMax !== undefined;
        const formatValue = (value: unknown) => Number(value).toFixed(isNormalized ? 3 : 1);

        const refMin = item?.payload?.[`${ds.id}__refMin`];
        const refMax = item?.payload?.[`${ds.id}__refMax`];
        const rangeLabel =
          refMin !== undefined &&
          refMax !== undefined &&
          refMin !== null &&
          refMax !== null
            ? ` (ref. range: ${formatValue(refMin)} - ${formatValue(refMax)})`
            : "";

        return {
          name: ds.name,
          value: `${formatValue(item?.value)}${isNormalized ? "" : ` ${ds.unit}`}${rangeLabel}`,
        };
      })
      .filter(Boolean) as Array<{ name: string; value: string }>;

    if (!rows.length) return null;

    return (
      <div className="rounded-xl border border-slate-200 bg-white px-3 py-2 shadow-lg">
        <p className="mb-1 text-[11px] font-semibold text-slate-500">
          {typeof label === "number" || typeof label === "string"
            ? format(new Date(label), "MMM d, yyyy")
            : String(label)}
        </p>
        <div className="space-y-1">
          {rows.map((row) => (
            <div key={row.name} className="flex items-baseline justify-between gap-3 text-[12px] leading-4">
              <span className="min-w-0 truncate font-medium text-slate-700">{row.name}</span>
              <span className="shrink-0 font-semibold text-slate-900">{row.value}</span>
            </div>
          ))}
        </div>
      </div>
    );
  };

export const createLineEndLabel = (
  text: string,
  color: string,
  yOffset: number,
  lastIndex: number
) =>
  (props: any) => {
    const { x, y, index } = props;

    if (index !== lastIndex || x === undefined || y === undefined) return null;

    return (
      <text
        x={x - 6}
        y={y + yOffset}
        textAnchor="end"
        fill={color}
        fontSize={10}
        fontWeight="700"
        paintOrder="stroke"
        stroke="white"
        strokeWidth={3}
        className="pointer-events-none select-none"
      >
        {text}
      </text>
    );
  };