import type { LucideIcon } from 'lucide-react';
import { LabelList, type TooltipProps } from 'recharts';

import { memo, ReactNode, useMemo } from 'react';

import {
  Area,
  AreaChart,
  Bar,
  BarChart,
  CartesianGrid,
  Cell,
  CHART_COLORS,
  ChartContainer,
  ChartTooltip,
  Legend,
  Pie,
  PieChart,
  XAxis,
  YAxis,
} from '@/Components/ui/chart';
import { EmptyState } from '@/Components/ui/empty-state';
import type { ActivationFunnelStage } from '@/types/admin';

const defaultDateFormatter = (v: string) =>
  new Date(v).toLocaleDateString(undefined, { month: 'short', day: 'numeric' });

// ---------------------------------------------------------------------------
// AdminAreaChart
// ---------------------------------------------------------------------------

interface AdminAreaChartProps<T> {
  data: T[];
  dataKey: string;
  name: string;
  height?: number;
  emptyIcon?: LucideIcon;
  emptyTitle?: string;
  emptyDescription?: string;
  gradientId?: string;
  xAxisKey?: string;
  xAxisFormatter?: (v: string) => string;
}

function AdminAreaChartInner<T>({
  data,
  dataKey,
  name,
  height = 300,
  emptyIcon,
  emptyTitle = 'No data yet',
  emptyDescription = 'Data will appear here once available.',
  gradientId = 'adminAreaGradient',
  xAxisKey = 'date',
  xAxisFormatter = defaultDateFormatter,
}: AdminAreaChartProps<T>) {
  if (data.length === 0) {
    return (
      <EmptyState icon={emptyIcon} title={emptyTitle} description={emptyDescription} size="sm" />
    );
  }

  return (
    <ChartContainer height={height}>
      <AreaChart data={data}>
        <defs>
          <linearGradient id={gradientId} x1="0" y1="0" x2="0" y2="1">
            <stop offset="5%" stopColor="hsl(var(--primary))" stopOpacity={0.3} />
            <stop offset="95%" stopColor="hsl(var(--primary))" stopOpacity={0} />
          </linearGradient>
        </defs>
        <CartesianGrid strokeDasharray="3 3" className="stroke-muted" />
        <XAxis dataKey={xAxisKey} tickFormatter={xAxisFormatter} className="text-xs" />
        <YAxis allowDecimals={false} className="text-xs" />
        <ChartTooltip />
        <Area
          type="monotone"
          dataKey={dataKey}
          name={name}
          stroke="hsl(var(--primary))"
          fill={`url(#${gradientId})`}
          strokeWidth={2}
          animationDuration={800}
          animationBegin={200}
        />
      </AreaChart>
    </ChartContainer>
  );
}

export const AdminAreaChart = memo(AdminAreaChartInner) as typeof AdminAreaChartInner;

// ---------------------------------------------------------------------------
// AdminBarChart
// ---------------------------------------------------------------------------

interface AdminBarChartProps<T> {
  data: T[];
  dataKey: string;
  xAxisKey: string;
  name: string;
  height?: number;
  emptyIcon?: LucideIcon;
  emptyTitle?: string;
  emptyDescription?: string;
  fillColor?: string;
  children?: ReactNode;
}

function AdminBarChartInner<T>({
  data,
  dataKey,
  xAxisKey,
  name,
  height = 250,
  emptyIcon,
  emptyTitle = 'No data yet',
  emptyDescription = 'Data will appear here once available.',
  fillColor = 'hsl(var(--primary))',
  children,
}: AdminBarChartProps<T>) {
  if (data.length === 0) {
    return (
      <EmptyState icon={emptyIcon} title={emptyTitle} description={emptyDescription} size="sm" />
    );
  }

  return (
    <ChartContainer height={height}>
      <BarChart data={data}>
        <CartesianGrid strokeDasharray="3 3" className="stroke-muted" />
        <XAxis dataKey={xAxisKey} className="text-xs" />
        <YAxis allowDecimals={false} className="text-xs" />
        <ChartTooltip />
        {children ?? (
          <Bar
            dataKey={dataKey}
            name={name}
            fill={fillColor}
            radius={[4, 4, 0, 0]}
            animationDuration={600}
          />
        )}
      </BarChart>
    </ChartContainer>
  );
}

export const AdminBarChart = memo(AdminBarChartInner) as typeof AdminBarChartInner;

// ---------------------------------------------------------------------------
// AdminPieChart
// ---------------------------------------------------------------------------

interface AdminPieChartProps<T> {
  data: T[];
  dataKey: string;
  nameKey: string;
  height?: number;
  emptyIcon?: LucideIcon;
  emptyTitle?: string;
  emptyDescription?: string;
}

function AdminPieChartInner<T>({
  data,
  dataKey,
  nameKey,
  height = 250,
  emptyIcon,
  emptyTitle = 'No data yet',
  emptyDescription = 'Data will appear here once available.',
}: AdminPieChartProps<T>) {
  const cells = useMemo(
    () =>
      data.map((_entry, index) => (
        <Cell key={`cell-${index}`} fill={CHART_COLORS[index % CHART_COLORS.length]} />
      )),
    [data],
  );

  if (data.length === 0) {
    return (
      <EmptyState icon={emptyIcon} title={emptyTitle} description={emptyDescription} size="sm" />
    );
  }

  return (
    <ChartContainer height={height}>
      <PieChart>
        <Pie
          data={data}
          dataKey={dataKey}
          nameKey={nameKey}
          cx="50%"
          cy="50%"
          outerRadius={80}
          label={({ name, value }) => `${name}: ${value}`}
          animationDuration={800}
          animationBegin={100}
        >
          {cells}
        </Pie>
        <ChartTooltip />
        <Legend />
      </PieChart>
    </ChartContainer>
  );
}

export const AdminPieChart = memo(AdminPieChartInner) as typeof AdminPieChartInner;

// ---------------------------------------------------------------------------
// AdminFunnelChart
// ---------------------------------------------------------------------------

interface AdminFunnelChartProps {
  data: ActivationFunnelStage[];
  height?: number;
}

function AdminFunnelChartInner({ data, height = 300 }: AdminFunnelChartProps) {
  if (data.length === 0 || data.every((d) => d.count === 0)) {
    return (
      <EmptyState
        title="No funnel data yet"
        description="Activation funnel data will appear once users sign up."
        size="sm"
      />
    );
  }

  return (
    <ChartContainer height={height}>
      <BarChart data={data} layout="vertical" margin={{ left: 20, right: 60 }}>
        <CartesianGrid strokeDasharray="3 3" className="stroke-muted" horizontal={false} />
        <XAxis type="number" allowDecimals={false} className="text-xs" />
        <YAxis type="category" dataKey="stage" width={160} className="text-xs" tickLine={false} />
        <ChartTooltip
          formatter={
            ((
              value: number | undefined,
              _name: string,
              props: { payload: ActivationFunnelStage },
            ) => [
              `${value ?? 0} users (${props.payload.conversion_rate}%)`,
              'Count',
            ]) as TooltipProps['formatter']
          }
        />
        <Bar
          dataKey="count"
          name="Users"
          fill="hsl(var(--primary))"
          radius={[0, 4, 4, 0]}
          animationDuration={600}
        >
          <LabelList dataKey="count" position="right" className="fill-foreground text-xs" />
        </Bar>
      </BarChart>
    </ChartContainer>
  );
}

export const AdminFunnelChart = memo(AdminFunnelChartInner);
