import {
  Area,
  AreaChart,
  CartesianGrid,
  Line,
  LineChart,
  XAxis,
  YAxis,
  type XAxisProps,
  type YAxisProps,
} from "recharts";
import { ChartTooltip, ChartTooltipContent } from "~/components/primitives/charts/Chart";
import { CHART_MARGIN } from "./ChartBar";
import { useChartContext } from "./ChartContext";
import { ChartLineInvalid, ChartLineLoading, ChartLineNoData } from "./ChartLoading";
import { useHasNoData } from "./ChartRoot";
import { defaultYAxisTickFormatter, useYAxisWidth } from "./useYAxisWidth";
// Legend is now rendered by ChartRoot outside the chart container

type CurveType =
  | "basis"
  | "basisClosed"
  | "basisOpen"
  | "linear"
  | "linearClosed"
  | "natural"
  | "monotoneX"
  | "monotoneY"
  | "monotone"
  | "step"
  | "stepBefore"
  | "stepAfter";

// ============================================================================
// COMPOUND COMPONENT API
// ============================================================================

export type ChartLineRendererProps = {
  /** Line curve type */
  lineType?: CurveType;
  /** Custom X-axis props to merge with defaults */
  xAxisProps?: Partial<XAxisProps>;
  /** Custom Y-axis props to merge with defaults */
  yAxisProps?: Partial<YAxisProps>;
  /** Render as stacked area chart instead of line chart */
  stacked?: boolean;
  /** Custom tooltip label formatter */
  tooltipLabelFormatter?: (label: string, payload: any[]) => string;
  /** Optional formatter for numeric tooltip values (e.g. bytes, duration) */
  tooltipValueFormatter?: (value: number) => string;
  /** Width injected by ResponsiveContainer */
  width?: number;
  /** Height injected by ResponsiveContainer */
  height?: number;
};

/**
 * Line chart renderer for the compound component system.
 * Must be used within a Chart.Root.
 *
 * @example
 * ```tsx
 * <Chart.Root config={config} data={data} dataKey="day">
 *   <Chart.Line type="step" />
 *   <Chart.Legend simple />
 * </Chart.Root>
 * ```
 */
export function ChartLineRenderer({
  lineType = "step",
  xAxisProps: xAxisPropsProp,
  yAxisProps: yAxisPropsProp,
  stacked = false,
  tooltipLabelFormatter,
  tooltipValueFormatter,
  width,
  height,
}: ChartLineRendererProps) {
  const {
    config,
    data,
    dataKey,
    dataKeys: _dataKeys,
    visibleSeries,
    state,
    highlight,
    setActivePayload,
    showLegend,
  } = useChartContext();
  const hasNoData = useHasNoData();
  const yAxisTickFormatter = yAxisPropsProp?.tickFormatter ?? defaultYAxisTickFormatter;
  const computedYAxisWidth = useYAxisWidth(data, visibleSeries, yAxisTickFormatter);

  // Render loading/error states
  if (state === "loading") {
    return <ChartLineLoading />;
  } else if (state === "noData" || hasNoData) {
    return <ChartLineNoData />;
  } else if (state === "invalid") {
    return <ChartLineInvalid />;
  }

  // Get the x-axis ticks based on tooltip state
  const xAxisTicks =
    highlight.tooltipActive && data.length > 2
      ? [data[0]?.[dataKey], data[data.length - 1]?.[dataKey]]
      : undefined;

  const xAxisConfig = {
    dataKey,
    tickLine: false,
    axisLine: false,
    tickMargin: 10,
    ticks: xAxisTicks,
    interval: "preserveStartEnd" as const,
    tick: {
      fill: "var(--color-text-dimmed)",
      fontSize: 11,
      style: { fontVariantNumeric: "tabular-nums" },
    },
    ...xAxisPropsProp,
  };

  const yAxisConfig = {
    axisLine: false,
    tickLine: false,
    tickMargin: 8,
    width: computedYAxisWidth,
    tick: {
      fill: "var(--color-text-dimmed)",
      fontSize: 11,
      style: { fontVariantNumeric: "tabular-nums" },
    },
    tickFormatter: yAxisTickFormatter,
    ...yAxisPropsProp,
  };

  // Handle mouse leave to also reset highlight
  const handleMouseLeave = () => {
    highlight.setTooltipActive(false);
    highlight.reset();
  };

  // Render stacked area chart if stacked prop is true
  if (stacked && visibleSeries.length > 1) {
    return (
      <AreaChart
        data={data}
        width={width}
        height={height}
        stackOffset="none"
        margin={CHART_MARGIN}
        onMouseMove={(e: any) => {
          if (e?.activePayload?.length) {
            setActivePayload(e.activePayload, e.activeTooltipIndex);
            highlight.setTooltipActive(true);
          } else {
            highlight.setTooltipActive(false);
          }
        }}
        onMouseLeave={handleMouseLeave}
      >
        <CartesianGrid vertical={false} stroke="var(--color-grid-bright)" strokeDasharray="3 3" />
        <XAxis {...xAxisConfig} />
        <YAxis {...yAxisConfig} />
        {/* When legend is shown below, render tooltip with cursor only (no content popup) */}
        <ChartTooltip
          cursor={{ stroke: "rgba(255, 255, 255, 0.1)", strokeWidth: 1 }}
          content={
            showLegend ? (
              () => null
            ) : (
              <ChartTooltipContent indicator="line" valueFormatter={tooltipValueFormatter} />
            )
          }
          labelFormatter={tooltipLabelFormatter}
        />
        {/* Note: Legend is now rendered by ChartRoot outside the chart container */}
        {visibleSeries.map((key) => (
          <Area
            key={key}
            type={lineType}
            dataKey={key}
            stroke={config[key]?.color}
            fill={config[key]?.color}
            fillOpacity={0.6}
            strokeWidth={1}
            stackId="stack"
            isAnimationActive={false}
          />
        ))}
      </AreaChart>
    );
  }

  return (
    <LineChart
      accessibilityLayer
      data={data}
      width={width}
      height={height}
      margin={CHART_MARGIN}
      onMouseMove={(e: any) => {
        if (e?.activePayload?.length) {
          setActivePayload(e.activePayload, e.activeTooltipIndex);
          highlight.setTooltipActive(true);
        } else {
          highlight.setTooltipActive(false);
        }
      }}
      onMouseLeave={handleMouseLeave}
    >
      <CartesianGrid vertical={false} stroke="var(--color-grid-bright)" strokeDasharray="3 3" />
      <XAxis {...xAxisConfig} />
      <YAxis {...yAxisConfig} />
      {/* When legend is shown below, render tooltip with cursor only (no content popup) */}
      <ChartTooltip
        cursor={{ stroke: "rgba(255, 255, 255, 0.1)", strokeWidth: 1 }}
        content={
          showLegend ? () => null : <ChartTooltipContent valueFormatter={tooltipValueFormatter} />
        }
        labelFormatter={tooltipLabelFormatter}
      />
      {/* Note: Legend is now rendered by ChartRoot outside the chart container */}
      {visibleSeries.map((key) => (
        <Line
          key={key}
          dataKey={key}
          type={lineType}
          stroke={config[key]?.color}
          strokeWidth={1}
          dot={{ r: 1.5, fill: config[key]?.color, strokeWidth: 0 }}
          activeDot={{ r: 4 }}
          isAnimationActive={false}
        />
      ))}
    </LineChart>
  );
}
