"use client";
import LoadingSpinner from "@/components/ui/spinner";
import { api } from "@/lib/trpc";
import { use, useEffect, useRef, useState } from "react";
import spacetime from "spacetime";
import { predefinedRanges } from "@/lib/dates";
import { useSearchParams } from "next/navigation";
import { parseISO, format as fmt } from "date-fns";
import { DatePickerInput } from '@mantine/dates';
import { Calendar1, MenuIcon } from "lucide-react";
import { Anchor, Button, ButtonGroup, Menu } from "@mantine/core";
import { useTooltip, useTooltipInPortal, defaultStyles } from '@visx/tooltip';
// import PieChart from "./PieChart";
import { Cell, LabelList, Pie, PieChart, Tooltip } from "recharts";

import { useTimezone } from "@/lib/userLocalSettings/client";
import TimeseriesChart from "./Timeseries";

const parseDateRangeFromQuery = (): Date[] | undefined => {
    const searchParams = useSearchParams();
    if (!searchParams.has("dateRange")) return undefined;

    const range = searchParams.get("dateRange")!
        .split(",")
        .map((date) => parseISO(date));
    return range;

}

const updateHistory = (dateRange: Date[]) => {
    const start = dateRange[0];
    const end = dateRange[1];
    const startStr = spacetime(start).format("iso-short");
    const endStr = spacetime(end).format("iso-short");
    const searchParams = new URLSearchParams();
    searchParams.set("dateRange", `${startStr},${endStr}`);
    history.replaceState(null, "", `?${searchParams.toString()}`);
};

export default function AnalyticsView() {
    const datePickerRef = useRef<HTMLButtonElement>(null);

    const { data: metrics } = api.metrics.list.useQuery();
    const drugsList = metrics?.filter((metric) => metric.type === "drug");

    const initialDateRange: [Date, Date] = (() => {
        const range = parseDateRangeFromQuery();
        if (range && range.length === 2) {
            return range as [Date, Date];
        }
        return [
            // spacetime.now().subtract(1, "week").toNativeDate(),
            parseISO(spacetime.now(useTimezone()).format("iso-short")),
            parseISO(spacetime.now(useTimezone()).format("iso-short")),
        ];
    })();

    const [dateRange, setDateRange] = useState(initialDateRange);
    const [datePickerRange, setDatePickerRange] = useState(initialDateRange);
    const [hideSleep, setHideSleep] = useState(false);

    useEffect(() => {
        if (datePickerRef.current?.getAttribute("aria-expanded") === "false") {
            setDateRange(datePickerRange);
            updateHistory(datePickerRange);
        }
    }, [datePickerRange]);

    const { containerRef, TooltipInPortal } = useTooltipInPortal({
        // TooltipInPortal is rendered in a separate child of <body /> and positioned
        // with page coordinates which should be updated on scroll. consider using
        // Tooltip or TooltipWithBounds if you don't need to render inside a Portal
        scroll: true,
    });

    const rawCategoryFrequencies = api.hours.categoryFrequencies.useQuery({
        dateRange,
        timezone: useTimezone(),
    }).data?.filter(
        (category) => category.categoryCode != undefined
    ) ?? [];

    const categoryFrequencies = hideSleep ? rawCategoryFrequencies.filter((category) => category.categoryCode > 1) : rawCategoryFrequencies;

    const maybeExtendWindow = (dateRange: Date[]) => {
        // If distance between dates is less than 2 days, extend the first date back by 14 days
        if (spacetime(dateRange[0]).diff(dateRange[1], "day") < 2) {
            return [
                spacetime(dateRange[0]).subtract(14, "day").toNativeDate(),
                dateRange[1]
            ];
        }
        return [dateRange[0], dateRange[1]];
    }

    const weightData = api.measurements.getTimeseries.useQuery({
        dateRange: maybeExtendWindow(dateRange) as [Date, Date],
        timezone: useTimezone(),
        metricName: "weight"
    }).data ?? [];

    return (
        <div className="px-4 flex flex-col">
            <div className="flex justify-between">
                <h1>Analytics for&nbsp;
                    {dateRange[0].getUTCDate() == dateRange[1].getUTCDate()
                        ? spacetime(dateRange[0]).unixFmt("MMM dd, yyyy")
                        : dateRange.map((d) => spacetime(d).unixFmt("MMM dd, yyyy")).join(" to ")
                    }
                </h1>
                {/* <DateRangePicker
                    showOneCalendar
                    appearance="subtle"
                    size="lg"
                    ranges={predefinedRanges}
                    character=" &ndash; "
                    format="MMM dd, yyyy"
                    value={dateRange}
                    onChange={setDateRange}
                    style={{ width: 300, textAlignLast: "center" }}
                    placement="bottomEnd"
                    renderValue={(value, format) => {
                        if (fmt(value[0], format) === fmt(value[1], format)) {
                            return fmt(value[0], format);
                        }
                        return `${fmt(value[0], format)} - ${fmt(value[1], format)}`;
                    }}
                /> */}
                <div className="flex">
                    <DatePickerInput
                        ref={datePickerRef}
                        type="range"
                        value={datePickerRange}
                        onChange={setDatePickerRange}
                        classNames={{
                            calendarHeader: "text-accent",
                        }}
                        highlightToday
                        allowSingleDateInRange
                        leftSection={<Calendar1 size={18} strokeWidth={1} />}
                        leftSectionPointerEvents="none"
                    />
                    <Menu position="bottom-end">
                        <Menu.Target>
                            <Button>
                                <MenuIcon size={18} />
                            </Button>
                        </Menu.Target>

                        <Menu.Dropdown>
                            {predefinedRanges.map((range) => (
                                <Menu.Item
                                    className="py-1 px-2"
                                    onClick={() => setDatePickerRange(range.value)}
                                >
                                    <Anchor
                                        size="xs"
                                    >
                                        {range.label}
                                    </Anchor>
                                </Menu.Item>
                            ))}
                        </Menu.Dropdown>
                    </Menu></div>
            </div>

            <div className="mt-8 pt-4 flex gap-4">
                <h2>Time</h2>
                {categoryFrequencies.length === 0 ? <LoadingSpinner /> :
                    <div className="w-full flex flex-col lg:flex-row gap-4">

                        <PieChart width={500} height={500} startAngle={180} endAngle={0} >
                            <Pie data={categoryFrequencies} dataKey="percentage" nameKey="categoryName" label={false}
                                paddingAngle={0} stroke={(c) => console.log(c)}>
                                {categoryFrequencies.sort(
                                    (a, b) => b.count - a.count
                                ).map((c, _i) => (
                                    <Cell key={`pie-category-${c.id}`} fill={c.background}
                                        style={{ outline: 'none !important' }}
                                    />
                                ))}
                            </Pie>
                            <Tooltip />
                        </PieChart>

                        <div className="grow">
                            <div className="flex flex-col justify-evenly h-full">
                                <div>
                                    <div className="grid font-bold border-b border-gray-200 pl-4"
                                        style={{
                                            gridTemplateColumns: "1fr 1fr"
                                        }}
                                    >
                                        <div className="whitespace-nowrap ">
                                            Total
                                        </div>
                                        <div>
                                            {categoryFrequencies.reduce((acc, category) => acc + category.count, 0)} hours
                                        </div></div>
                                    {
                                        categoryFrequencies
                                            .sort((a, b) => b.count - a.count)
                                            .map((category, i) => (

                                                <div key={i} className="grid p-1 pl-4"
                                                    style={{
                                                        gridTemplateColumns: "1fr 1fr",
                                                        color: category.inverse,
                                                        backgroundColor: category.color
                                                    }}
                                                >
                                                    <div className="whitespace-nowrap">
                                                        {category.categoryName ?? "[Unallocated]"}
                                                    </div>
                                                    <div>
                                                        {category.count} hours
                                                    </div></div>
                                            ))
                                    }</div>
                            </div>
                        </div>
                        <div className="mt-4 bg-accent w-fit p-2 border border-primary rounded-md cursor-pointer flex flex-col items-center">
                            Sleep
                            <ButtonGroup className="mt-2">
                                <Button
                                    onClick={() => setHideSleep(true)}
                                    color={hideSleep ? "gray" : "primary"}
                                >
                                    Hide
                                </Button>
                                <Button
                                    onClick={() => setHideSleep(false)}
                                    color={hideSleep ? "primary" : "gray"}
                                >
                                    Show
                                </Button>
                            </ButtonGroup>
                        </div>
                    </div>
                }
            </div>
            <div className="mt-8 pt-4 flex gap-4">
                <h2 className="">Drugs</h2>
                <div>
                    {
                        !drugsList ? <LoadingSpinner /> :
                            <ul>
                                {drugsList.map((drug) => (
                                    <li key={drug.id}>
                                        {drug.name}:
                                    </li>
                                ))}
                            </ul>
                    }
                </div>

            </div>
            <div className="mt-8 pt-4 flex gap-4">
                <h2>Weight</h2>
                {
                    weightData.length === 0 ? <LoadingSpinner /> :
                        <div>
                            <TimeseriesChart data={weightData} timeseriesName="Weight" />
                        </div>
                }
            </div>

        </div >

    );
}