import { TrendingUp } from 'lucide-react';
import { useId, useMemo, useState } from 'react';
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts';
import {
    Card,
    CardContent,
    CardDescription,
    CardFooter,
    CardHeader,
    CardTitle,
} from '@/components/ui/card';
import {
    ChartContainer,
    ChartTooltip,
    ChartTooltipContent,
} from '@/components/ui/chart';
import type { ChartConfig } from '@/components/ui/chart';
import { cn } from '@/lib/utils';

export type PerformanceTimeRange =
    | 'today'
    | 'this_week'
    | 'last_30_days'
    | 'custom';

type PerformanceMetricKey =
    | 'bookings'
    | 'revenue'
    | 'completed'
    | 'new_customers';

type PerformanceSummaryItem = {
    value: number;
    change: number | null;
};

type PerformanceSeriesPoint = {
    date: string;
    label: string;
    bookings: number;
    revenue: number;
    completed: number;
    new_customers: number;
};

export type DashboardPerformance = {
    time_range: PerformanceTimeRange;
    period_label: string;
    summary: Record<PerformanceMetricKey, PerformanceSummaryItem>;
    series: PerformanceSeriesPoint[];
};

const chartConfig = {
    bookings: {
        label: 'Appointments',
        color: 'var(--chart-1)',
    },
    revenue: {
        label: 'Sales revenue',
        color: 'var(--chart-2)',
    },
    completed: {
        label: 'Completed',
        color: 'var(--chart-3)',
    },
    new_customers: {
        label: 'New customers',
        color: 'var(--chart-4)',
    },
} satisfies ChartConfig;

const metricOrder: PerformanceMetricKey[] = [
    'bookings',
    'revenue',
    'completed',
    'new_customers',
];

function formatMetricValue(key: PerformanceMetricKey, value: number): string {
    if (key === 'revenue') {
        return new Intl.NumberFormat('en-US', {
            style: 'currency',
            currency: 'USD',
            minimumFractionDigits: 0,
            maximumFractionDigits: 0,
        }).format(value / 100);
    }

    return value.toLocaleString();
}

function formatTooltipValue(key: PerformanceMetricKey, value: number): string {
    if (key === 'revenue') {
        return new Intl.NumberFormat('en-US', {
            style: 'currency',
            currency: 'USD',
            minimumFractionDigits: 2,
            maximumFractionDigits: 2,
        }).format(value / 100);
    }

    return value.toLocaleString();
}

function TrendLabel({ change }: { change: number | null }) {
    if (change === null) {
        return (
            <span className="text-xs text-muted-foreground">No prior data</span>
        );
    }

    const isPositive = change >= 0;

    return (
        <span
            className={cn(
                'text-xs font-medium tabular-nums',
                isPositive
                    ? 'text-emerald-600 dark:text-emerald-400'
                    : 'text-red-600 dark:text-red-400',
            )}
        >
            {isPositive ? '+' : ''}
            {change}%
        </span>
    );
}

type DashboardPerformanceChartProps = {
    performance: DashboardPerformance;
};

export function DashboardPerformanceChart({
    performance,
}: DashboardPerformanceChartProps) {
    const gradientId = useId().replace(/:/g, '');
    const [activeMetric, setActiveMetric] =
        useState<PerformanceMetricKey>('bookings');

    const chartData = useMemo(() => performance.series, [performance.series]);
    const activeSummary = performance.summary[activeMetric];
    const fillGradientId = `fill-${activeMetric}-${gradientId}`;

    const tickGap =
        performance.series.length > 60
            ? 48
            : performance.series.length > 14
              ? 32
              : 24;

    return (
        <Card className="py-4 sm:py-0">
            <CardHeader className="flex flex-col items-stretch border-b p-0! sm:flex-row">
                <div className="flex flex-1 flex-col justify-center gap-3 px-6 py-4 sm:py-6">
                    <div className="space-y-1">
                        <CardTitle>Performance</CardTitle>
                        <CardDescription>
                            Daily trends · {performance.period_label}
                        </CardDescription>
                    </div>
                </div>
                <div className="grid grid-cols-2 sm:flex sm:flex-1">
                    {metricOrder.map((metric) => (
                        <button
                            key={metric}
                            type="button"
                            data-active={activeMetric === metric}
                            className="flex flex-1 flex-col justify-center gap-1 border-t px-4 py-4 text-left transition-colors even:border-l data-[active=true]:bg-muted/50 sm:border-t-0 sm:border-l sm:px-6 sm:py-6"
                            onClick={() => setActiveMetric(metric)}
                        >
                            <span className="text-xs text-muted-foreground">
                                {chartConfig[metric].label}
                            </span>
                            <span className="text-lg leading-none font-semibold tabular-nums sm:text-2xl">
                                {formatMetricValue(
                                    metric,
                                    performance.summary[metric].value,
                                )}
                            </span>
                            <TrendLabel
                                change={performance.summary[metric].change}
                            />
                        </button>
                    ))}
                </div>
            </CardHeader>
            <CardContent className="px-2 pt-4 sm:px-6 sm:pt-6">
                <ChartContainer
                    config={chartConfig}
                    className="aspect-auto h-[260px] w-full"
                >
                    <AreaChart
                        accessibilityLayer
                        data={chartData}
                        margin={{
                            left: 12,
                            right: 12,
                        }}
                    >
                        <CartesianGrid vertical={false} />
                        <XAxis
                            dataKey="label"
                            tickLine={false}
                            axisLine={false}
                            tickMargin={8}
                            minTickGap={tickGap}
                        />
                        <YAxis hide />
                        <ChartTooltip
                            cursor={false}
                            content={
                                <ChartTooltipContent
                                    className="w-[160px]"
                                    labelFormatter={(_, payload) => {
                                        const point = payload?.[0]?.payload as
                                            | PerformanceSeriesPoint
                                            | undefined;

                                        if (!point) {
                                            return '';
                                        }

                                        return new Date(
                                            point.date,
                                        ).toLocaleDateString(undefined, {
                                            weekday: 'short',
                                            month: 'short',
                                            day: 'numeric',
                                        });
                                    }}
                                    formatter={(value) =>
                                        formatTooltipValue(
                                            activeMetric,
                                            Number(value),
                                        )
                                    }
                                />
                            }
                        />
                        <defs>
                            <linearGradient
                                id={fillGradientId}
                                x1="0"
                                y1="0"
                                x2="0"
                                y2="1"
                            >
                                <stop
                                    offset="5%"
                                    stopColor={`var(--color-${activeMetric})`}
                                    stopOpacity={0.8}
                                />
                                <stop
                                    offset="95%"
                                    stopColor={`var(--color-${activeMetric})`}
                                    stopOpacity={0.1}
                                />
                            </linearGradient>
                        </defs>
                        <Area
                            dataKey={activeMetric}
                            type="natural"
                            fill={`url(#${fillGradientId})`}
                            fillOpacity={0.4}
                            stroke={`var(--color-${activeMetric})`}
                            strokeWidth={2}
                        />
                    </AreaChart>
                </ChartContainer>
            </CardContent>
            <CardFooter className="border-t px-6 py-4">
                <div className="flex w-full flex-col gap-2 text-sm sm:flex-row sm:items-center sm:justify-between">
                    <div className="grid gap-1">
                        <div className="flex items-center gap-2 leading-none font-medium">
                            {activeSummary.change !== null ? (
                                <>
                                    {activeSummary.change >= 0
                                        ? 'Trending up'
                                        : 'Trending down'}{' '}
                                    by {Math.abs(activeSummary.change)}% vs
                                    prior period
                                    <TrendingUp
                                        className={cn(
                                            'size-4',
                                            activeSummary.change < 0 &&
                                                'rotate-180',
                                        )}
                                    />
                                </>
                            ) : (
                                <span className="font-normal text-muted-foreground">
                                    No comparison data for prior period
                                </span>
                            )}
                        </div>
                        <div className="leading-none text-muted-foreground">
                            {chartConfig[activeMetric].label} ·{' '}
                            {performance.period_label}
                        </div>
                    </div>
                    <span className="text-lg font-semibold tabular-nums">
                        {formatMetricValue(activeMetric, activeSummary.value)}
                    </span>
                </div>
            </CardFooter>
        </Card>
    );
}
