"use client";

import { useEffect, useMemo, useRef } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { CloudSun, Droplets, Sunrise, Sunset, Wind, X } from "lucide-react";
import { DayForecastCharts } from "@/components/charts/day-forecast-charts";
import { ForecastIcon } from "@/components/forecast/forecast-icon";
import { ForecastSources } from "@/components/forecast/forecast-sources";
import { Card } from "@/components/ui/card";
import { useI18n } from "@/lib/i18n";
import { cn } from "@/lib/utils";
import {
  formatForecastRainfall,
  formatForecastTemperature,
  formatForecastWind,
  getForecastCondition,
  isForecastHourPast,
} from "@/lib/forecast-utils";
import type { DailyForecast, ForecastSource, HourlyForecast } from "@/types/forecast";

function formatHour(value: string | null) {
  if (!value) return "—";
  return value.slice(11, 16);
}

function getMaximumWind(hours: HourlyForecast[]) {
  return hours.reduce<number | null>((maximum, hour) => {
    if (hour.windSpeed === null) return maximum;
    return maximum === null ? hour.windSpeed : Math.max(maximum, hour.windSpeed);
  }, null);
}

function DayMetric({ icon: Icon, label, value }: { icon: typeof Droplets; label: string; value: string }) {
  return (
    <div className="rounded-2xl border border-white/30 bg-white/20 p-3 dark:border-white/10 dark:bg-white/5">
      <Icon className="size-4 text-sky-700 dark:text-sky-300" />
      <p className="mt-3 text-[0.68rem] font-semibold uppercase tracking-[0.14em] text-slate-500 dark:text-slate-400">{label}</p>
      <p className="mt-1 text-base font-semibold">{value}</p>
    </div>
  );
}

export function DayForecastModal({
  day,
  hours,
  locationName,
  sources,
  onClose,
}: {
  day: DailyForecast | null;
  hours: HourlyForecast[];
  locationName: string;
  sources: ForecastSource[];
  onClose: () => void;
}) {
  const { language, locale, t } = useI18n();
  const closeButtonRef = useRef<HTMLButtonElement>(null);
  const maximumWind = useMemo(() => getMaximumWind(hours), [hours]);

  useEffect(() => {
    if (!day) return;
    const previouslyFocused = document.activeElement instanceof HTMLElement ? document.activeElement : null;
    const previousOverflow = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    closeButtonRef.current?.focus();

    function handleKeyDown(event: KeyboardEvent) {
      if (event.key === "Escape") onClose();
    }

    window.addEventListener("keydown", handleKeyDown);
    return () => {
      window.removeEventListener("keydown", handleKeyDown);
      document.body.style.overflow = previousOverflow;
      previouslyFocused?.focus();
    };
  }, [day, onClose]);

  const formattedDate = day
    ? new Intl.DateTimeFormat(locale, { weekday: "long", day: "numeric", month: "long", timeZone: "UTC" }).format(new Date(`${day.date}T12:00:00Z`))
    : "";

  return (
    <AnimatePresence>
      {day ? (
        <motion.div
          className="fixed inset-0 z-[90] flex items-center justify-center bg-slate-950/55 p-0 backdrop-blur-md sm:p-4 lg:p-8"
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          onPointerDown={onClose}
        >
          <motion.section
            role="dialog"
            aria-modal="true"
            aria-labelledby="day-forecast-title"
            className="weather-scrollbar h-full w-full overflow-y-auto bg-gradient-to-b from-sky-100/95 via-slate-100/95 to-white/95 shadow-2xl dark:from-slate-900/95 dark:via-slate-950/95 dark:to-slate-950/95 sm:max-w-6xl sm:rounded-[2rem] sm:border sm:border-white/30 dark:sm:border-white/10"
            initial={{ opacity: 0, y: 28, scale: 0.985 }}
            animate={{ opacity: 1, y: 0, scale: 1 }}
            exit={{ opacity: 0, y: 20, scale: 0.99 }}
            transition={{ type: "spring", stiffness: 260, damping: 28 }}
            onPointerDown={(event) => event.stopPropagation()}
          >
            <div className="mx-auto max-w-6xl space-y-5 p-4 pb-8 sm:p-6 lg:p-8">
              <div className="flex items-start justify-between gap-4">
                <div>
                  <p className="flex items-center gap-2 text-xs font-semibold uppercase tracking-[0.16em] text-sky-700 dark:text-sky-300">
                    <CloudSun className="size-4" />
                    {t("forecast.dayDetails")}
                  </p>
                  <h2 id="day-forecast-title" className="mt-2 text-2xl font-semibold tracking-tight sm:text-3xl">{locationName}</h2>
                  <p className="mt-1 capitalize text-slate-600 dark:text-slate-300">{formattedDate}</p>
                </div>
                <button
                  ref={closeButtonRef}
                  type="button"
                  aria-label={t("forecast.closeDetails")}
                  className="rounded-full border border-white/35 bg-white/35 p-3 text-slate-700 transition hover:bg-white/60 focus-visible:outline focus-visible:outline-2 focus-visible:outline-sky-600 dark:border-white/10 dark:bg-white/10 dark:text-slate-100 dark:hover:bg-white/20"
                  onClick={onClose}
                >
                  <X className="size-5" />
                </button>
              </div>

              <Card className="overflow-hidden bg-gradient-to-br from-sky-500/20 via-white/25 to-indigo-400/15 p-5 dark:from-sky-700/20 dark:via-white/5 dark:to-indigo-500/15 sm:p-6">
                <div className="flex flex-col justify-between gap-5 sm:flex-row sm:items-center">
                  <div>
                    <p className="text-sm text-slate-600 dark:text-slate-300">{getForecastCondition(day.weatherCode, language)}</p>
                    <div className="mt-2 flex items-end gap-4">
                      <ForecastIcon code={day.weatherCode} className="mb-2 size-14 text-sky-700 dark:text-sky-300" />
                      <p className="text-6xl font-semibold tracking-[-0.08em] sm:text-7xl">{formatForecastTemperature(day.temperatureMax, language)}</p>
                      <p className="mb-2 text-2xl text-slate-500 dark:text-slate-400">{formatForecastTemperature(day.temperatureMin, language)}</p>
                    </div>
                  </div>
                  <div className="grid grid-cols-2 gap-2 sm:min-w-[22rem]">
                    <DayMetric icon={Droplets} label={t("forecast.precipitation")} value={formatForecastRainfall(day.precipitation, language)} />
                    <DayMetric icon={Wind} label={t("forecast.maxWind")} value={formatForecastWind(maximumWind, language)} />
                    <DayMetric icon={Sunrise} label={t("forecast.sunrise")} value={formatHour(day.sunrise)} />
                    <DayMetric icon={Sunset} label={t("forecast.sunset")} value={formatHour(day.sunset)} />
                  </div>
                </div>
              </Card>

              <Card className="overflow-hidden p-4 sm:p-5">
                <h3 className="text-sm font-semibold">{t("forecast.hourlyForDay")}</h3>
                <div className="weather-scrollbar -mx-4 mt-4 overflow-x-auto px-4 pb-2 sm:-mx-5 sm:px-5">
                  <ul className="flex min-w-max gap-2">
                    {hours.map((hour) => {
                      const isPast = isForecastHourPast(hour.time);
                      return (
                        <li
                          key={hour.time}
                          className={cn(
                            "w-[5.2rem] rounded-2xl border border-white/35 bg-white/25 px-2 py-3 text-center dark:border-white/10 dark:bg-white/5",
                            isPast && "opacity-45",
                          )}
                          title={isPast ? t("forecast.pastHour") : getForecastCondition(hour.weatherCode, language)}
                        >
                          <p className="text-xs font-medium text-slate-600 dark:text-slate-300">{formatHour(hour.time)}</p>
                          <ForecastIcon code={hour.weatherCode} className="mx-auto my-3 size-6 text-sky-600 dark:text-sky-300" />
                          <p className="text-lg font-semibold tracking-tight">{formatForecastTemperature(hour.temperature, language)}</p>
                          <p className="mt-2 flex items-center justify-center gap-1 text-[0.66rem] text-sky-700 dark:text-sky-300">
                            <Droplets className="size-3" />
                            {hour.precipitationProbability === null ? "—" : `${hour.precipitationProbability}%`}
                          </p>
                        </li>
                      );
                    })}
                  </ul>
                </div>
              </Card>

              <DayForecastCharts hours={hours} />

              <ForecastSources sources={sources} />
            </div>
          </motion.section>
        </motion.div>
      ) : null}
    </AnimatePresence>
  );
}
