import DayNavigator from '@/Components/DayNavigator';
import PrintButton from '@/Components/PrintButton';
import { Badge } from '@/Components/ui/badge';
import {
    ChartConfig,
    ChartContainer,
    ChartTooltip,
    ChartTooltipContent,
} from '@/Components/ui/chart';
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
import MetricChart from '@/Pages/Metric/MetricChart';
import MetricPeriodSummary from '@/Pages/Metric/MetricPeriodSummary';
import { BodyComposition, MetricPeriod, User } from '@/types';
import { Head, router, usePage } from '@inertiajs/react';
import dayjs, { Dayjs } from 'dayjs';
import { useState } from 'react';
import { CartesianGrid, Line, LineChart, XAxis, YAxis } from 'recharts';

interface BodyCompositionPeriodPoint {
    date: string;
    weight: number | null;
    bmi: number | null;
}

interface BodyCompositionPeriodSummary {
    average: number | null;
    min: number | null;
    max: number | null;
    averageBmi: number | null;
    count: number;
}

interface MetricDetailProps {
    measures: BodyComposition[];
    trend: { measured_at: string; weight: number | null; bmi: number | null }[];
    patient: User;
    availableDates: string[];
    period: MetricPeriod<
        BodyCompositionPeriodPoint,
        BodyCompositionPeriodSummary
    > | null;
}

const fmt = (v: number | undefined | null, digits = 1) =>
    v === null || v === undefined ? '-' : Number(v).toFixed(digits);

function MetricRow({
    label,
    value,
    unit,
}: {
    label: string;
    value: string;
    unit?: string;
}) {
    return (
        <div className="flex justify-between border-b border-zinc-100 py-1 text-sm">
            <span className="text-zinc-500">{label}</span>
            <span className="font-medium">
                {value}
                {unit ? ` ${unit}` : ''}
            </span>
        </div>
    );
}

export default function BodyCompositionMetricDetail({
    measures,
    trend,
    patient,
    availableDates,
    period,
}: MetricDetailProps) {
    const user = usePage().props.auth.user;
    const now = dayjs();
    const { filters } = usePage().props;
    const [date, setDate] = useState(filters?.date || now.format('YYYY-MM-DD'));

    const onDateChange = (updatedDate: Dayjs) => {
        const dateString = dayjs(updatedDate).format('YYYY-MM-DD');
        setDate(dateString);
        router.get(
            route('body-composition.detail', { patient: patient.id }),
            { date: dateString },
            { preserveState: true, preserveScroll: true, replace: true },
        );
    };

    const onRangeChange = (from: Dayjs, to: Dayjs) => {
        router.get(
            route('body-composition.detail', { patient: patient.id }),
            {
                from: from.format('YYYY-MM-DD'),
                to: to.format('YYYY-MM-DD'),
            },
            { preserveState: true, preserveScroll: true, replace: true },
        );
    };

    const backLinkLabel =
        patient.id === user.id
            ? 'Dashboard'
            : `${patient.name} ${patient.surname}`;

    const trendData = trend.map((t) => ({
        date: dayjs(t.measured_at).format('DD/MM'),
        weight: t.weight,
        bmi: t.bmi,
    }));

    const periodTrendData = period
        ? period.data.map((point) => ({
              date: dayjs(point.date).format(
                  period.byMonth ? 'MM/YYYY' : 'DD/MM',
              ),
              weight: point.weight,
              bmi: point.bmi,
          }))
        : [];

    const chartData = period ? periodTrendData : trendData;

    const chartConfig: ChartConfig = {
        weight: { label: 'Peso (kg)', color: '#05A7A0' },
        bmi: { label: 'BMI', color: '#69cac6' },
    };

    const renderMeasure = (measure: BodyComposition) => (
        <div key={measure.id} className="mt-12">
            <div className="mb-4 flex flex-wrap gap-2">
                <Badge>{dayjs(measure.measured_at).format('HH:mm:ss')}</Badge>
                {measure.device_name && (
                    <Badge variant="outline">
                        {measure.device_label ?? measure.device_name}
                    </Badge>
                )}
            </div>

            <div className="grid grid-cols-1 gap-6 md:grid-cols-3">
                <div>
                    <div className="mb-2 font-semibold text-zinc-700">
                        Misure base
                    </div>
                    <MetricRow
                        label="Peso"
                        value={fmt(measure.weight)}
                        unit="kg"
                    />
                    <MetricRow
                        label="Altezza"
                        value={fmt(measure.height, 0)}
                        unit="cm"
                    />
                    <MetricRow label="BMI" value={fmt(measure.bmi)} />
                    <MetricRow
                        label="Età corporea"
                        value={
                            measure.body_age != null
                                ? String(measure.body_age)
                                : '-'
                        }
                        unit="anni"
                    />
                </div>
                <div>
                    <div className="mb-2 font-semibold text-zinc-700">
                        Composizione
                    </div>
                    <MetricRow
                        label="Grasso corporeo"
                        value={fmt(measure.body_fat)}
                        unit="%"
                    />
                    {measure.body_fat_stage != null && (
                        <MetricRow
                            label="Stadio grasso"
                            value={String(measure.body_fat_stage)}
                        />
                    )}
                    <MetricRow
                        label="Massa magra"
                        value={fmt(measure.fat_free_mass)}
                        unit="kg"
                    />
                    <MetricRow
                        label="Massa grassa"
                        value={fmt(measure.fat_mass)}
                        unit="kg"
                    />
                    <MetricRow
                        label="Massa acqua"
                        value={fmt(measure.hydration)}
                        unit="kg"
                    />
                    <MetricRow
                        label="Massa ossea"
                        value={fmt(measure.bone_mass)}
                        unit="kg"
                    />
                    <MetricRow
                        label="Massa muscolare"
                        value={fmt(measure.skeletal_muscle)}
                        unit="kg"
                    />
                    {measure.skeletal_muscle_stage != null && (
                        <MetricRow
                            label="Stadio muscolare"
                            value={String(measure.skeletal_muscle_stage)}
                        />
                    )}
                    {measure.visceral_fat != null && (
                        <MetricRow
                            label="Grasso viscerale"
                            value={fmt(measure.visceral_fat, 0)}
                        />
                    )}
                    {measure.visceral_fat_stage != null && (
                        <MetricRow
                            label="Stadio viscerale"
                            value={String(measure.visceral_fat_stage)}
                        />
                    )}
                </div>
                <div>
                    <div className="mb-2 font-semibold text-zinc-700">
                        Metabolismo / Cardiovascolare
                    </div>
                    <MetricRow
                        label="Metabolismo basale"
                        value={
                            measure.basal_metabolism != null
                                ? String(measure.basal_metabolism)
                                : '-'
                        }
                        unit="kcal"
                    />
                    <MetricRow
                        label="Velocità onda polso"
                        value={fmt(measure.pulse_wave_velocity)}
                        unit="m/s"
                    />
                </div>
            </div>
        </div>
    );

    return (
        <AuthenticatedLayout
            backLink={route('dashboard.personal', { target: patient.id })}
            backLinkLabel={backLinkLabel}
        >
            <Head title="Composizione corporea" />

            <div className="py-2">
                <div className="mx-auto max-w-7xl sm:px-6 lg:px-8">
                    <div className="overflow-hidden sm:rounded-lg">
                        <div className="p-6 text-gray-900">
                            <div className="scroll-m-20 pb-8 text-4xl font-semibold tracking-tight lg:text-5xl">
                                Composizione corporea
                            </div>
                            <div className="flex justify-center gap-2 md:justify-end">
                                <PrintButton />
                                <DayNavigator
                                    date={dayjs(date)}
                                    onChange={onDateChange}
                                    availableDates={availableDates}
                                    range={
                                        period
                                            ? {
                                                  from: dayjs(period.from),
                                                  to: dayjs(period.to),
                                              }
                                            : null
                                    }
                                    onRangeChange={onRangeChange}
                                />
                            </div>

                            {chartData.length > 0 && (
                                <MetricChart>
                                    <div className="w-full">
                                        <div className="mb-2 text-left text-sm text-zinc-500">
                                            {period
                                                ? `Andamento dal ${dayjs(period.from).format('DD/MM/YYYY')} al ${dayjs(period.to).format('DD/MM/YYYY')}`
                                                : 'Andamento ultimo mese'}
                                        </div>
                                        <ChartContainer
                                            config={chartConfig}
                                            className="h-[260px] w-full"
                                        >
                                            <LineChart
                                                data={chartData}
                                                margin={{
                                                    top: 8,
                                                    bottom: 8,
                                                    left: 24,
                                                    right: 24,
                                                }}
                                            >
                                                <CartesianGrid stroke="#cdedec" />
                                                <XAxis
                                                    dataKey="date"
                                                    tick={{
                                                        fill: '#69cac6',
                                                        fontSize: 12,
                                                    }}
                                                />
                                                <YAxis
                                                    yAxisId="left"
                                                    tick={{
                                                        fill: '#69cac6',
                                                        fontSize: 12,
                                                    }}
                                                />
                                                <YAxis
                                                    yAxisId="right"
                                                    orientation="right"
                                                    tick={{
                                                        fill: '#69cac6',
                                                        fontSize: 12,
                                                    }}
                                                />
                                                <ChartTooltip
                                                    content={
                                                        <ChartTooltipContent />
                                                    }
                                                />
                                                <Line
                                                    yAxisId="left"
                                                    dataKey="weight"
                                                    stroke="var(--color-weight)"
                                                    strokeWidth={2}
                                                    dot={{ r: 3 }}
                                                    isAnimationActive={false}
                                                />
                                                <Line
                                                    yAxisId="right"
                                                    dataKey="bmi"
                                                    stroke="var(--color-bmi)"
                                                    strokeWidth={2}
                                                    dot={{ r: 3 }}
                                                    isAnimationActive={false}
                                                />
                                            </LineChart>
                                        </ChartContainer>
                                    </div>
                                </MetricChart>
                            )}

                            {period && (
                                <div className="flex w-full justify-center">
                                    <div className="w-full max-w-2xl">
                                        <MetricPeriodSummary
                                            average={
                                                period.summary?.average != null
                                                    ? `${period.summary.average} kg`
                                                    : null
                                            }
                                            max={
                                                period.summary?.max != null
                                                    ? `${period.summary.max} kg`
                                                    : null
                                            }
                                            min={
                                                period.summary?.min != null
                                                    ? `${period.summary.min} kg`
                                                    : null
                                            }
                                            caption={
                                                period.summary
                                                    ? `Peso su ${period.summary.count} misurazioni${period.summary.averageBmi != null ? ` · BMI medio ${period.summary.averageBmi}` : ''} dal ${dayjs(period.from).format('DD/MM/YYYY')} al ${dayjs(period.to).format('DD/MM/YYYY')}`
                                                    : null
                                            }
                                        />
                                    </div>
                                </div>
                            )}

                            {!period && measures.length === 0 && (
                                <div className="mt-8 text-center text-zinc-500">
                                    Nessuna misura per la data selezionata.
                                </div>
                            )}

                            {!period && measures.map(renderMeasure)}

                            <div className="flex w-full justify-center">
                                <div className="max-w-2xl">
                                    <div className="mt-8 text-zinc-500 print:hidden">
                                        La bilancia bioimpedenziometrica stima
                                        peso, BMI, percentuale di grasso
                                        corporeo, grasso viscerale, massa
                                        muscolare scheletrica, metabolismo
                                        basale ed età corporea. Gli stadi (1-12)
                                        indicano la classificazione relativa del
                                        valore secondo il produttore. Il BMI
                                        normale è 18.5-24.9.
                                    </div>
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </AuthenticatedLayout>
    );
}
