import { useEffect, useId, useState } from 'react';
import {
    Area,
    AreaChart,
    Bar,
    BarChart,
    CartesianGrid,
    Cell,
    Legend,
    Line,
    LineChart,
    Pie,
    PieChart,
    ResponsiveContainer,
    Tooltip,
    XAxis,
    YAxis,
} from 'recharts';
import type { ChartSpec } from '@/lib/agent-stream';

const COLOR_VARIABLES = [
    '--chart-1',
    '--chart-2',
    '--chart-3',
    '--chart-4',
    '--chart-5',
];

const DEFAULT_CHART_COLORS = [
    'rgb(80, 48, 168)',
    'rgb(26, 42, 80)',
    'rgb(245, 158, 11)',
    'rgb(239, 68, 68)',
    'rgb(6, 182, 212)',
];

function resolveThemeColor(variable: string): string {
    if (typeof document === 'undefined') {
        return DEFAULT_CHART_COLORS[0];
    }

    const probe = document.createElement('span');
    probe.style.color = `var(${variable})`;
    probe.style.display = 'none';
    document.documentElement.appendChild(probe);
    const resolved = getComputedStyle(probe).color;
    probe.remove();

    return resolved && resolved !== '' ? resolved : DEFAULT_CHART_COLORS[0];
}

function useChartColors(): string[] {
    const [colors, setColors] = useState(DEFAULT_CHART_COLORS);

    useEffect(() => {
        const readColors = () => {
            setColors(
                COLOR_VARIABLES.map(
                    (variable, index) =>
                        resolveThemeColor(variable) ||
                        DEFAULT_CHART_COLORS[
                            index % DEFAULT_CHART_COLORS.length
                        ],
                ),
            );
        };

        readColors();
        const observer = new MutationObserver(readColors);
        observer.observe(document.documentElement, {
            attributes: true,
            attributeFilter: ['class'],
        });

        return () => observer.disconnect();
    }, []);

    return colors;
}

function toRows(chart: ChartSpec): Array<Record<string, string | number>> {
    return chart.labels.map((label, index) => {
        const row: Record<string, string | number> = { label };

        for (const series of chart.series) {
            row[series.name] = series.data[index] ?? 0;
        }

        return row;
    });
}

function chartCurrency(
    chart: ChartSpec,
    fallback?: string,
): string | undefined {
    const metaCurrency = chart.meta?.currency;

    return typeof metaCurrency === 'string' && metaCurrency !== ''
        ? metaCurrency
        : fallback;
}

export function ChartMessage({
    chart,
    currency,
    artifactId,
}: {
    chart: ChartSpec;
    currency?: string;
    artifactId: string;
}) {
    const data = toRows(chart);
    const primary = chart.series[0]?.name ?? 'value';
    const colors = useChartColors();
    const titleId = useId();
    const resolvedCurrency = chartCurrency(chart, currency);
    const numberFormatter = new Intl.NumberFormat(undefined, {
        maximumFractionDigits: 2,
    });
    const currencyFormatter = resolvedCurrency
        ? new Intl.NumberFormat(undefined, {
              style: 'currency',
              currency: resolvedCurrency,
              maximumFractionDigits: 2,
          })
        : numberFormatter;
    const formatValue = (value: number) => currencyFormatter.format(value);
    const hasData = data.length > 0 && chart.series.length > 0;
    const denseLabels = data.length > 12;
    const description = hasData
        ? `${chart.title}. ${chart.series.length} series across ${data.length} periods.`
        : `${chart.title}. No data is available for this period.`;

    const chartMargin = {
        top: 8,
        right: 12,
        left: 8,
        bottom: denseLabels ? 48 : 8,
    };

    return (
        <figure
            className="my-3 w-full max-w-2xl min-w-0 overflow-hidden rounded-xl border border-border bg-card p-4"
            aria-labelledby={titleId}
            data-artifact-id={artifactId}
        >
            <figcaption
                id={titleId}
                className="mb-1 text-sm font-medium text-foreground"
            >
                {chart.title}
            </figcaption>
            <p className="mb-3 text-xs text-muted-foreground">{description}</p>
            {!hasData ? (
                <div className="flex min-h-40 items-center justify-center rounded-lg bg-muted/40 px-4 text-center text-sm text-muted-foreground">
                    No chartable data was returned for this period.
                </div>
            ) : (
                <div className="h-[clamp(14rem,42vw,18rem)] w-full min-w-0">
                    <ResponsiveContainer
                        width="100%"
                        height="100%"
                        minWidth={0}
                    >
                        {chart.type === 'bar' ? (
                            <BarChart data={data} margin={chartMargin}>
                                <CartesianGrid
                                    strokeDasharray="3 3"
                                    stroke="rgba(148, 163, 184, 0.35)"
                                />
                                <XAxis
                                    dataKey="label"
                                    interval={
                                        denseLabels ? 'preserveStartEnd' : 0
                                    }
                                    angle={denseLabels ? -35 : 0}
                                    textAnchor={denseLabels ? 'end' : 'middle'}
                                    height={denseLabels ? 56 : 30}
                                    tick={{
                                        fontSize: 11,
                                        fill: 'rgb(100, 116, 139)',
                                    }}
                                />
                                <YAxis
                                    width={72}
                                    tick={{
                                        fontSize: 11,
                                        fill: 'rgb(100, 116, 139)',
                                    }}
                                    tickFormatter={formatValue}
                                />
                                <Tooltip
                                    contentStyle={{
                                        background: 'rgb(255, 255, 255)',
                                        borderColor: 'rgb(226, 232, 240)',
                                        color: 'rgb(15, 23, 42)',
                                    }}
                                    formatter={(value) =>
                                        formatValue(Number(value))
                                    }
                                />
                                <Legend />
                                {chart.series.map((series, index) => (
                                    <Bar
                                        key={series.name}
                                        dataKey={series.name}
                                        fill={
                                            colors[index % colors.length] ??
                                            DEFAULT_CHART_COLORS[0]
                                        }
                                    />
                                ))}
                            </BarChart>
                        ) : chart.type === 'area' ? (
                            <AreaChart data={data} margin={chartMargin}>
                                <CartesianGrid
                                    strokeDasharray="3 3"
                                    stroke="rgba(148, 163, 184, 0.35)"
                                />
                                <XAxis
                                    dataKey="label"
                                    interval={
                                        denseLabels ? 'preserveStartEnd' : 0
                                    }
                                    angle={denseLabels ? -35 : 0}
                                    textAnchor={denseLabels ? 'end' : 'middle'}
                                    height={denseLabels ? 56 : 30}
                                    tick={{
                                        fontSize: 11,
                                        fill: 'rgb(100, 116, 139)',
                                    }}
                                />
                                <YAxis
                                    width={72}
                                    tick={{
                                        fontSize: 11,
                                        fill: 'rgb(100, 116, 139)',
                                    }}
                                    tickFormatter={formatValue}
                                />
                                <Tooltip
                                    contentStyle={{
                                        background: 'rgb(255, 255, 255)',
                                        borderColor: 'rgb(226, 232, 240)',
                                        color: 'rgb(15, 23, 42)',
                                    }}
                                    formatter={(value) =>
                                        formatValue(Number(value))
                                    }
                                />
                                <Legend />
                                {chart.series.map((series, index) => (
                                    <Area
                                        key={series.name}
                                        type="monotone"
                                        dataKey={series.name}
                                        stroke={
                                            colors[index % colors.length] ??
                                            DEFAULT_CHART_COLORS[0]
                                        }
                                        fill={
                                            colors[index % colors.length] ??
                                            DEFAULT_CHART_COLORS[0]
                                        }
                                        fillOpacity={0.2}
                                        strokeWidth={2}
                                    />
                                ))}
                            </AreaChart>
                        ) : chart.type === 'pie' ? (
                            <PieChart
                                margin={{
                                    top: 8,
                                    right: 8,
                                    bottom: 8,
                                    left: 8,
                                }}
                            >
                                <Tooltip
                                    contentStyle={{
                                        background: 'rgb(255, 255, 255)',
                                        borderColor: 'rgb(226, 232, 240)',
                                        color: 'rgb(15, 23, 42)',
                                    }}
                                    formatter={(value) =>
                                        formatValue(Number(value))
                                    }
                                />
                                <Legend />
                                <Pie
                                    data={data}
                                    dataKey={primary}
                                    nameKey="label"
                                    outerRadius="72%"
                                    label={{
                                        fill: 'rgb(15, 23, 42)',
                                        fontSize: 11,
                                    }}
                                >
                                    {data.map((_, index) => (
                                        <Cell
                                            key={index}
                                            fill={
                                                colors[index % colors.length] ??
                                                DEFAULT_CHART_COLORS[0]
                                            }
                                        />
                                    ))}
                                </Pie>
                            </PieChart>
                        ) : (
                            <LineChart data={data} margin={chartMargin}>
                                <CartesianGrid
                                    strokeDasharray="3 3"
                                    stroke="rgba(148, 163, 184, 0.35)"
                                />
                                <XAxis
                                    dataKey="label"
                                    interval={
                                        denseLabels ? 'preserveStartEnd' : 0
                                    }
                                    angle={denseLabels ? -35 : 0}
                                    textAnchor={denseLabels ? 'end' : 'middle'}
                                    height={denseLabels ? 56 : 30}
                                    tick={{
                                        fontSize: 11,
                                        fill: 'rgb(100, 116, 139)',
                                    }}
                                />
                                <YAxis
                                    width={72}
                                    tick={{
                                        fontSize: 11,
                                        fill: 'rgb(100, 116, 139)',
                                    }}
                                    tickFormatter={formatValue}
                                />
                                <Tooltip
                                    contentStyle={{
                                        background: 'rgb(255, 255, 255)',
                                        borderColor: 'rgb(226, 232, 240)',
                                        color: 'rgb(15, 23, 42)',
                                    }}
                                    formatter={(value) =>
                                        formatValue(Number(value))
                                    }
                                />
                                <Legend />
                                {chart.series.map((series, index) => (
                                    <Line
                                        key={series.name}
                                        type="monotone"
                                        dataKey={series.name}
                                        stroke={
                                            colors[index % colors.length] ??
                                            DEFAULT_CHART_COLORS[0]
                                        }
                                        strokeWidth={2}
                                        dot={false}
                                        activeDot={{ r: 4 }}
                                    />
                                ))}
                            </LineChart>
                        )}
                    </ResponsiveContainer>
                </div>
            )}
        </figure>
    );
}
