import {
    Bar,
    BarChart,
    CartesianGrid,
    Cell,
    Line,
    LineChart as RechartsLineChart,
    Pie,
    PieChart,
    XAxis,
    YAxis,
} from 'recharts';
import {
    Card,
    CardContent,
    CardDescription,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
import {
    ChartContainer,
    ChartLegend,
    ChartLegendContent,
    ChartTooltip,
    ChartTooltipContent,
    type ChartConfig,
} from '@/components/ui/chart';
import { cn, formatCurrency } from '@/lib/utils';

export function KpiCard({
    label,
    value,
    hint,
    format = 'currency',
    tone = 'default',
}: {
    label: string;
    value: string | number;
    hint?: string;
    format?: 'currency' | 'number' | 'text' | 'percent';
    tone?: 'default' | 'positive' | 'negative' | 'warning';
}) {
    const display =
        format === 'currency'
            ? formatCurrency(value)
            : format === 'number'
              ? Number(value).toLocaleString('fr-FR')
              : format === 'percent'
                ? `${value} %`
                : String(value);

    return (
        <Card>
            <CardHeader className="pb-2">
                <CardDescription>{label}</CardDescription>
                <CardTitle
                    className={cn(
                        'text-2xl tabular-nums',
                        tone === 'positive' && 'text-emerald-700 dark:text-emerald-400',
                        tone === 'negative' && 'text-destructive',
                        tone === 'warning' && 'text-amber-700 dark:text-amber-400',
                    )}
                >
                    {display}
                </CardTitle>
            </CardHeader>
            {hint ? (
                <CardContent className="pt-0 text-xs text-muted-foreground">
                    {hint}
                </CardContent>
            ) : null}
        </Card>
    );
}

type Series = {
    key: string;
    label: string;
    color: string;
};

function EmptyChart({ message }: { message: string }) {
    return (
        <p className="flex h-[220px] items-center justify-center text-sm text-muted-foreground">
            {message}
        </p>
    );
}

export function LineChart({
    items,
    series,
    labelKey = 'label',
    height = 280,
    exportTitle,
}: {
    items: Array<Record<string, string | number>>;
    series: Series[];
    labelKey?: string;
    height?: number;
    exportTitle?: string;
}) {
    if (items.length === 0) {
        return (
            <EmptyChart message="Aucune donnée sur la période sélectionnée." />
        );
    }

    const chartConfig = series.reduce<ChartConfig>((config, s) => {
        config[s.key] = { label: s.label, color: s.color };
        return config;
    }, {});

    const data = items.map((item) => {
        const row: Record<string, string | number> = {
            label: String(item[labelKey] ?? ''),
        };

        for (const s of series) {
            row[s.key] = Number(item[s.key] ?? 0);
        }

        return row;
    });

    return (
        <div
            {...(exportTitle
                ? { 'data-dashboard-chart': true, 'data-chart-title': exportTitle }
                : {})}
        >
            <ChartContainer
                config={chartConfig}
                className="aspect-auto w-full"
                style={{ height }}
            >
                <RechartsLineChart
                    data={data}
                    margin={{ top: 8, right: 12, left: 4, bottom: 0 }}
                >
                    <CartesianGrid vertical={false} strokeDasharray="3 3" />
                    <XAxis
                        dataKey="label"
                        tickLine={false}
                        axisLine={false}
                        tickMargin={8}
                        minTickGap={24}
                    />
                    <YAxis
                        tickLine={false}
                        axisLine={false}
                        tickMargin={8}
                        width={72}
                        tickFormatter={(value: number) =>
                            formatCurrency(value).replace(/\s/g, '\u00a0')
                        }
                    />
                    <ChartTooltip
                        cursor={{ strokeDasharray: '4 4' }}
                        content={
                            <ChartTooltipContent
                                formatter={(value) => formatCurrency(value)}
                            />
                        }
                    />
                    <ChartLegend content={<ChartLegendContent />} />
                    {series.map((s) => (
                        <Line
                            key={s.key}
                            type="monotone"
                            dataKey={s.key}
                            stroke={`var(--color-${s.key})`}
                            strokeWidth={2}
                            dot={{ r: 3, strokeWidth: 0 }}
                            activeDot={{ r: 5, strokeWidth: 0 }}
                        />
                    ))}
                </RechartsLineChart>
            </ChartContainer>
        </div>
    );
}

export function SimpleBarChart({
    items,
    valueKey,
    labelKey = 'label',
}: {
    items: Array<Record<string, string | number>>;
    valueKey: string;
    labelKey?: string;
}) {
    if (items.length === 0) {
        return (
            <EmptyChart message="Aucune donnée sur la période sélectionnée." />
        );
    }

    const chartConfig: ChartConfig = {
        value: { label: 'Montant', color: 'hsl(221 83% 53%)' },
    };

    const data = items.map((item) => ({
        label: String(item[labelKey] ?? ''),
        value: Number(item[valueKey] ?? 0),
    }));

    return (
        <ChartContainer config={chartConfig} className="aspect-auto h-[280px] w-full">
            <BarChart
                data={data}
                layout="vertical"
                margin={{ top: 0, right: 12, left: 0, bottom: 0 }}
            >
                <CartesianGrid horizontal={false} strokeDasharray="3 3" />
                <YAxis
                    dataKey="label"
                    type="category"
                    tickLine={false}
                    axisLine={false}
                    width={100}
                    tickMargin={8}
                />
                <XAxis
                    type="number"
                    tickLine={false}
                    axisLine={false}
                    tickFormatter={(value: number) => formatCurrency(value)}
                />
                <ChartTooltip
                    cursor={{ fill: 'hsl(var(--muted))', opacity: 0.4 }}
                    content={
                        <ChartTooltipContent
                            hideLabel
                            formatter={(value) => formatCurrency(value)}
                        />
                    }
                />
                <Bar dataKey="value" fill="var(--color-value)" radius={[0, 4, 4, 0]} />
            </BarChart>
        </ChartContainer>
    );
}

const CATEGORY_COLORS = [
    'hsl(221 83% 53%)',
    'hsl(160 84% 39%)',
    'hsl(32 95% 44%)',
    'hsl(0 72% 51%)',
    'hsl(262 83% 58%)',
];

export function StackedCategoryChart({
    items,
    exportTitle = 'Répartition globale',
}: {
    items: Array<{ label: string; amount: string; type?: string }>;
    exportTitle?: string;
}) {
    const total = items.reduce((sum, item) => sum + Number(item.amount), 0);

    if (total <= 0) {
        return (
            <EmptyChart message="Aucune dépense enregistrée sur la période." />
        );
    }

    const data = items
        .filter((item) => Number(item.amount) > 0)
        .map((item, index) => ({
            key: item.type ?? item.label,
            label: item.label,
            amount: Number(item.amount),
            fill: CATEGORY_COLORS[index % CATEGORY_COLORS.length],
        }));

    const chartConfig = data.reduce<ChartConfig>((config, item) => {
        config[item.key] = { label: item.label, color: item.fill };
        return config;
    }, {});

    return (
        <div className="space-y-4">
            <div
                data-dashboard-chart
                data-chart-title={exportTitle}
            >
                <ChartContainer config={chartConfig} className="mx-auto aspect-square max-h-[260px]">
                    <PieChart>
                        <ChartTooltip
                            content={
                                <ChartTooltipContent
                                    hideLabel
                                    formatter={(value) => formatCurrency(value)}
                                />
                            }
                        />
                        <Pie
                            data={data}
                            dataKey="amount"
                            nameKey="key"
                            innerRadius={56}
                            outerRadius={88}
                            paddingAngle={2}
                            strokeWidth={0}
                        >
                            {data.map((entry) => (
                                <Cell key={entry.key} fill={entry.fill} />
                            ))}
                        </Pie>
                        <ChartLegend content={<ChartLegendContent />} />
                    </PieChart>
                </ChartContainer>
            </div>
            <div className="space-y-2">
                {data.map((item) => (
                    <div
                        key={item.key}
                        className="flex items-center justify-between text-sm"
                    >
                        <span className="inline-flex items-center gap-2">
                            <span
                                className="inline-block h-2.5 w-2.5 rounded-full"
                                style={{ backgroundColor: item.fill }}
                            />
                            {item.label}
                        </span>
                        <span className="font-medium tabular-nums">
                            {formatCurrency(item.amount)}
                        </span>
                    </div>
                ))}
            </div>
        </div>
    );
}
