import DayNavigator from '@/Components/DayNavigator';
import ExportButton from '@/Components/ExportButton';
import PrintButton from '@/Components/PrintButton';
import AuthenticatedLayout from '@/Layouts/AuthenticatedLayout';
import LineMetricChart from '@/Pages/Metric/LineMetricChart';
import MetricMeasure from '@/Pages/Metric/MetricMeasure';
import MetricPeriodSummary from '@/Pages/Metric/MetricPeriodSummary';
import MetricSummaryCard from '@/Pages/Metric/MetricSummaryCard';
import {
    AggregatedMetricData,
    LabMeasure,
    LabTypeOption,
    MetricPeriod,
    User,
} from '@/types';
import { Head, router, usePage } from '@inertiajs/react';
import dayjs, { Dayjs } from 'dayjs';
import { useState } from 'react';

interface LabMetricDetailProps {
    measures: LabMeasure[];
    measuresByHour: AggregatedMetricData[];
    type: string;
    types: LabTypeOption[];
    patient: User;
    availableDates: string[];
    period: MetricPeriod | null;
    filters: { date: string; type: string };
}

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

    const current = types.find((t) => t.value === type) ?? types[0];
    const unit = current?.unit ?? '';
    const decimals = current?.decimals ?? 1;
    const label = current?.label ?? 'Esami ematici';

    const format = (value: number | null) =>
        value !== null ? `${value.toFixed(decimals)} ${unit}` : undefined;

    const navigate = (nextType: string, nextDate: string) => {
        router.get(
            route('lab.detail', { patient: patient.id }),
            { date: nextDate, type: nextType },
            { preserveState: true, preserveScroll: true, replace: true },
        );
    };

    const onDateChange = (updatedDate: Dayjs) => {
        const dateString = dayjs(updatedDate).format('YYYY-MM-DD');
        setDate(dateString);
        navigate(type, dateString);
    };

    const onTypeChange = (nextType: string) => {
        if (nextType === type) {
            return;
        }
        if (period) {
            // Keep the selected period when switching exam type.
            router.get(
                route('lab.detail', { patient: patient.id }),
                { from: period.from, to: period.to, type: nextType },
                { preserveState: true, preserveScroll: true, replace: true },
            );
            return;
        }
        navigate(nextType, date);
    };

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

    const periodData = period
        ? period.data.map((point) => ({
              date: dayjs(point.date).format(
                  period.byMonth ? 'MM/YYYY' : 'DD/MM',
              ),
              average: point.average,
              min: point.min,
              max: point.max,
          }))
        : [];

    const data = measuresByHour.map((measure) => ({
        date: dayjs(measure.date).format('HH:mm'),
        average: measure.average,
        min: measure.min,
        max: measure.max,
    }));

    const values = measures.map((m) => m.value);
    const min = values.length ? Math.min(...values) : null;
    const max = values.length ? Math.max(...values) : null;
    const avg = values.length
        ? values.reduce((s, v) => s + v, 0) / values.length
        : null;

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

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

            <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">
                                Esami ematici
                            </div>

                            <div className="flex flex-wrap gap-2 pb-6">
                                {types.map((option) => (
                                    <button
                                        key={option.value}
                                        type="button"
                                        onClick={() =>
                                            onTypeChange(option.value)
                                        }
                                        className={`rounded-full px-4 py-2 text-sm font-medium transition ${
                                            option.value === type
                                                ? 'bg-neutral-800 text-white'
                                                : 'bg-neutral-100 text-neutral-700 hover:bg-neutral-200'
                                        }`}
                                    >
                                        {option.label}
                                    </button>
                                ))}
                            </div>

                            <div className="flex justify-center gap-2 md:justify-end">
                                <PrintButton />
                                <ExportButton
                                    href={route('lab.detail.export', {
                                        patient: patient.id,
                                        type,
                                    })}
                                />
                                <DayNavigator
                                    date={dayjs(date)}
                                    onChange={onDateChange}
                                    availableDates={availableDates}
                                    range={
                                        period
                                            ? {
                                                  from: dayjs(period.from),
                                                  to: dayjs(period.to),
                                              }
                                            : null
                                    }
                                    onRangeChange={onRangeChange}
                                />
                            </div>
                            <div>
                                <LineMetricChart
                                    data={period ? periodData : data}
                                />
                            </div>
                            <div className="flex w-full justify-center">
                                <div className="max-w-2xl">
                                    {period && (
                                        <MetricPeriodSummary
                                            average={
                                                period.summary
                                                    ? format(
                                                          period.summary
                                                              .average,
                                                      )
                                                    : null
                                            }
                                            max={
                                                period.summary
                                                    ? format(period.summary.max)
                                                    : null
                                            }
                                            min={
                                                period.summary
                                                    ? format(period.summary.min)
                                                    : null
                                            }
                                            caption={
                                                period.summary
                                                    ? `${period.summary.count} misurazioni dal ${dayjs(period.from).format('DD/MM/YYYY')} al ${dayjs(period.to).format('DD/MM/YYYY')}`
                                                    : null
                                            }
                                        />
                                    )}
                                    {!period && (
                                        <div className="mt-8 flex flex-wrap gap-4">
                                            <MetricSummaryCard
                                                title="Massima"
                                                value={format(max)}
                                                className="bg-neutral-200"
                                            />
                                            <MetricSummaryCard
                                                title="Minima"
                                                value={format(min)}
                                                className="bg-neutral-100"
                                            />
                                            <MetricSummaryCard
                                                title="Media"
                                                value={format(avg)}
                                                className="bg-neutral-100"
                                            />
                                        </div>
                                    )}
                                    <div className="mt-8 text-zinc-500">
                                        {current?.description}
                                    </div>
                                    {!period && (
                                        <div className="mt-8">
                                            <h2 className="mb-4 font-semibold">
                                                Misurazioni di{' '}
                                                {label.toLowerCase()}
                                            </h2>
                                            <ul>
                                                {measures.map((measure) => (
                                                    <MetricMeasure
                                                        key={measure.id}
                                                        value={`${measure.value.toFixed(decimals)} ${unit}`}
                                                        measuredAt={dayjs(
                                                            measure.measured_at,
                                                        )}
                                                        deviceName={
                                                            measure.device_label ??
                                                            measure.device_name
                                                        }
                                                    />
                                                ))}
                                            </ul>
                                        </div>
                                    )}
                                </div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </AuthenticatedLayout>
    );
}
