"use client";

import { useEffect, useMemo, useState } from "react";
import { Bell, BellRing, Languages, MapPinned, Palette, Settings, Smartphone } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Card } from "@/components/ui/card";
import { LanguageToggle } from "@/components/ui/language-toggle";
import { ThemeToggle } from "@/components/ui/theme-toggle";
import { DEFAULT_STATION_ID } from "@/lib/constants";
import { useI18n } from "@/lib/i18n";
import { decodeBase64UrlKey, deletePushSubscription, fetchVapidPublicKey, savePushSubscription, sendTestPushNotification } from "@/lib/notification-api";
import { formatProvinceName, getProvinceForSelection, PROVINCES } from "@/lib/provinces";
import { useWeatherStore } from "@/lib/store";
import type { Province } from "@/types/province";

type NotificationSupportStatus = "checking" | "unconfigured" | "unsupported" | "needs-install" | "default" | "denied" | "granted";

function isStandaloneApp() {
  if (typeof window === "undefined") return false;
  const navigatorWithStandalone = window.navigator as Navigator & { standalone?: boolean };
  return window.matchMedia("(display-mode: standalone)").matches || navigatorWithStandalone.standalone === true;
}

function getNotificationSupportStatus(): NotificationSupportStatus {
  if (typeof window === "undefined") return "checking";
  if (!("Notification" in window) || !("serviceWorker" in navigator) || !("PushManager" in window)) return "unsupported";
  if (!isStandaloneApp()) return "needs-install";
  return Notification.permission;
}

function SettingsRow({ icon: Icon, title, description, children }: { icon: typeof Settings; title: string; description: string; children: React.ReactNode }) {
  return (
    <div className="flex flex-col gap-4 border-t border-border/65 py-4 first:border-t-0 first:pt-0 last:pb-0 sm:flex-row sm:items-center sm:justify-between">
      <div className="flex items-start gap-3">
        <div className="rounded-control border border-border/70 bg-surface-muted/70 p-2 text-accent">
          <Icon className="size-4" aria-hidden="true" />
        </div>
        <div>
          <h2 className="text-sm font-semibold">{title}</h2>
          <p className="mt-1 max-w-xl text-sm leading-6 text-muted">{description}</p>
        </div>
      </div>
      <div className="shrink-0">{children}</div>
    </div>
  );
}

export function SettingsPage() {
  const { language, t } = useI18n();
  const [notificationStatus, setNotificationStatus] = useState<NotificationSupportStatus>("checking");
  const [vapidPublicKey, setVapidPublicKey] = useState<string | null>(null);
  const [isSavingSubscription, setIsSavingSubscription] = useState(false);
  const [isSendingTestNotification, setIsSendingTestNotification] = useState(false);
  const [notificationMessage, setNotificationMessage] = useState<string | null>(null);
  const selectedStationId = useWeatherStore((state) => state.selectedStationId);
  const selectedLocation = useWeatherStore((state) => state.selectedLocation);
  const notificationsEnabled = useWeatherStore((state) => state.warningNotificationsEnabled);
  const provinceMode = useWeatherStore((state) => state.warningNotificationProvinceMode);
  const manualProvince = useWeatherStore((state) => state.warningNotificationProvince);
  const setNotificationsEnabled = useWeatherStore((state) => state.setWarningNotificationsEnabled);
  const setProvinceMode = useWeatherStore((state) => state.setWarningNotificationProvinceMode);
  const setManualProvince = useWeatherStore((state) => state.setWarningNotificationProvince);

  const selectedProvince = getProvinceForSelection(selectedLocation?.province, selectedStationId ?? DEFAULT_STATION_ID);
  const effectiveProvince = provinceMode === "manual" ? manualProvince : selectedProvince;
  const effectiveProvinceLabel = effectiveProvince ? formatProvinceName(effectiveProvince, language) : t("settings.notifications.noProvince");

  useEffect(() => {
    const abortController = new AbortController();
    const animationFrame = window.requestAnimationFrame(() => {
      setNotificationStatus(getNotificationSupportStatus());
      fetchVapidPublicKey(abortController.signal)
        .then((config) => {
          setVapidPublicKey(config.publicKey);
          if (!config.configured) setNotificationStatus("unconfigured");
        })
        .catch(() => setNotificationStatus("unconfigured"));
    });
    return () => {
      abortController.abort();
      window.cancelAnimationFrame(animationFrame);
    };
  }, []);

  useEffect(() => {
    if (!notificationsEnabled || !vapidPublicKey || !effectiveProvince || notificationStatus !== "granted") return;
    const province = effectiveProvince;
    let cancelled = false;

    async function syncSubscriptionProvince() {
      const registration = await navigator.serviceWorker?.getRegistration();
      const subscription = await registration?.pushManager.getSubscription();
      if (!subscription || cancelled) return;
      await savePushSubscription(subscription, province, language).catch(() => undefined);
    }

    syncSubscriptionProvince();
    return () => {
      cancelled = true;
    };
  }, [effectiveProvince, language, notificationStatus, notificationsEnabled, vapidPublicKey]);

  const notificationStatusLabel = useMemo(() => {
    switch (notificationStatus) {
      case "unconfigured":
        return t("settings.notifications.statusUnconfigured");
      case "unsupported":
        return t("settings.notifications.statusUnsupported");
      case "needs-install":
        return t("settings.notifications.statusNeedsInstall");
      case "denied":
        return t("settings.notifications.statusDenied");
      case "granted":
        return t("settings.notifications.statusGranted");
      case "default":
        return t("settings.notifications.statusReady");
      default:
        return t("settings.notifications.statusChecking");
    }
  }, [notificationStatus, t]);

  const canUsePush = Boolean(vapidPublicKey && effectiveProvince && notificationStatus !== "unsupported" && notificationStatus !== "needs-install" && notificationStatus !== "denied" && notificationStatus !== "unconfigured");

  async function getServiceWorkerRegistration() {
    if (!("serviceWorker" in navigator)) throw new Error("Service worker is not available.");
    return await navigator.serviceWorker.getRegistration() ?? await navigator.serviceWorker.register("/sw.js");
  }

  async function enableWarningNotifications() {
    if (!vapidPublicKey || !effectiveProvince) {
      setNotificationMessage(t("settings.notifications.saveError"));
      return;
    }
    if (!("Notification" in window)) {
      setNotificationStatus("unsupported");
      return;
    }
    setIsSavingSubscription(true);
    setNotificationMessage(null);
    try {
      const permission = Notification.permission === "granted" ? "granted" : await Notification.requestPermission();
      setNotificationStatus(permission);
      if (permission !== "granted") {
        setNotificationsEnabled(false);
        return;
      }
      const registration = await getServiceWorkerRegistration();
      const existingSubscription = await registration.pushManager.getSubscription();
      const subscription = existingSubscription ?? await registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: decodeBase64UrlKey(vapidPublicKey),
      });
      await savePushSubscription(subscription, effectiveProvince, language);
      setNotificationsEnabled(true);
      setNotificationMessage(t("settings.notifications.saveSuccess"));
    } catch {
      setNotificationsEnabled(false);
      setNotificationMessage(t("settings.notifications.saveError"));
    } finally {
      setIsSavingSubscription(false);
    }
  }

  async function disableWarningNotifications() {
    setIsSavingSubscription(true);
    setNotificationMessage(null);
    try {
      const registration = await navigator.serviceWorker?.getRegistration();
      const subscription = await registration?.pushManager.getSubscription();
      if (subscription) {
        await deletePushSubscription(subscription.endpoint).catch(() => undefined);
        await subscription.unsubscribe();
      }
      setNotificationsEnabled(false);
      setNotificationMessage(t("settings.notifications.disableSuccess"));
    } catch {
      setNotificationMessage(t("settings.notifications.saveError"));
    } finally {
      setIsSavingSubscription(false);
    }
  }

  async function sendTestNotification() {
    setIsSendingTestNotification(true);
    setNotificationMessage(null);
    try {
      const registration = await navigator.serviceWorker?.getRegistration();
      const subscription = await registration?.pushManager.getSubscription();
      if (!subscription) throw new Error("Push subscription is not available.");
      await sendTestPushNotification(subscription.endpoint);
      setNotificationMessage(t("settings.notifications.testSuccess"));
    } catch {
      setNotificationMessage(t("settings.notifications.testError"));
    } finally {
      setIsSendingTestNotification(false);
    }
  }

  return (
    <div className="space-y-6">
      <section>
        <p className="section-kicker flex items-center gap-2"><Settings className="size-4" />{t("settings.section")}</p>
        <h1 className="mt-2 text-3xl font-semibold tracking-tight">{t("settings.title")}</h1>
        <p className="mt-2 max-w-2xl text-sm leading-6 text-muted">{t("settings.description")}</p>
      </section>

      <Card className="p-4 sm:p-5">
        <SettingsRow icon={Languages} title={t("settings.language.title")} description={t("settings.language.description")}>
          <LanguageToggle />
        </SettingsRow>
        <SettingsRow icon={Palette} title={t("settings.theme.title")} description={t("settings.theme.description")}>
          <ThemeToggle />
        </SettingsRow>
      </Card>

      <Card className="p-4 sm:p-5">
        <div className="flex items-start gap-3">
          <div className="rounded-control border border-warning/30 bg-warning/10 p-2 text-warning">
            <BellRing className="size-4" aria-hidden="true" />
          </div>
          <div>
            <p className="text-[0.68rem] font-semibold uppercase tracking-[0.16em] text-warning">IMGW</p>
            <h2 className="mt-1 text-lg font-semibold tracking-tight">{t("settings.notifications.title")}</h2>
            <p className="mt-1 max-w-2xl text-sm leading-6 text-muted">{t("settings.notifications.description")}</p>
          </div>
        </div>

        <div className="mt-5 grid gap-3 lg:grid-cols-2">
          <div className="rounded-card border border-border/65 bg-surface-muted/45 p-4">
            <div className="flex items-start gap-3">
              <MapPinned className="mt-0.5 size-4 text-accent" aria-hidden="true" />
              <div>
                <h3 className="text-sm font-semibold">{t("settings.notifications.regionTitle")}</h3>
                <p className="mt-1 text-sm leading-6 text-muted">{t("settings.notifications.regionDescription", { province: effectiveProvinceLabel })}</p>
              </div>
            </div>

            <div className="mt-4 space-y-3">
              <label className="flex items-start gap-3 rounded-card border border-border/60 bg-surface px-3 py-3 text-sm">
                <input
                  type="radio"
                  name="warning-notification-province-mode"
                  checked={provinceMode === "selected"}
                  onChange={() => setProvinceMode("selected")}
                  className="mt-1 accent-accent"
                />
                <span>
                  <span className="block font-medium">{t("settings.notifications.regionSelected")}</span>
                  <span className="mt-0.5 block text-xs leading-5 text-muted">{selectedProvince ? formatProvinceName(selectedProvince, language) : t("settings.notifications.noProvince")}</span>
                </span>
              </label>
              <label className="flex items-start gap-3 rounded-card border border-border/60 bg-surface px-3 py-3 text-sm">
                <input
                  type="radio"
                  name="warning-notification-province-mode"
                  checked={provinceMode === "manual"}
                  onChange={() => {
                    setProvinceMode("manual");
                    if (!manualProvince) setManualProvince(selectedProvince ?? "mazowieckie");
                  }}
                  className="mt-1 accent-accent"
                />
                <span className="min-w-0 flex-1">
                  <span className="block font-medium">{t("settings.notifications.regionManual")}</span>
                  <select
                    aria-label={t("settings.notifications.regionManual")}
                    value={manualProvince ?? selectedProvince ?? "mazowieckie"}
                    disabled={provinceMode !== "manual"}
                    onChange={(event) => setManualProvince(event.target.value as Province)}
                    className="surface-control mt-2 w-full rounded-control px-3 py-2 text-sm disabled:opacity-60"
                  >
                    {PROVINCES.map((province) => (
                      <option key={province} value={province}>{formatProvinceName(province, language)}</option>
                    ))}
                  </select>
                </span>
              </label>
            </div>
          </div>

          <div className="rounded-card border border-border/65 bg-surface-muted/45 p-4">
            <div className="flex items-start gap-3">
              <Smartphone className="mt-0.5 size-4 text-accent" aria-hidden="true" />
              <div>
                <h3 className="text-sm font-semibold">{t("settings.notifications.deviceTitle")}</h3>
                <p className="mt-1 text-sm leading-6 text-muted">{notificationStatusLabel}</p>
              </div>
            </div>

            <div className="mt-4 rounded-card border border-border/60 bg-surface px-3 py-3 text-sm">
              <p className="font-medium">{t("settings.notifications.enable")}</p>
              <p className="mt-0.5 text-xs leading-5 text-muted">{t("settings.notifications.enableDescription")}</p>
              {notificationMessage && <p className="mt-3 text-xs font-medium text-accent">{notificationMessage}</p>}
            </div>

            <div className="mt-4 flex flex-col gap-2 sm:flex-row">
              <Button type="button" disabled={(!notificationsEnabled && !canUsePush) || isSavingSubscription} onClick={notificationsEnabled ? disableWarningNotifications : enableWarningNotifications}>
                <Bell className="size-4" />
                {isSavingSubscription
                  ? t("settings.notifications.saving")
                  : notificationsEnabled
                    ? t("settings.notifications.disable")
                    : t("settings.notifications.enableDevice")}
              </Button>
              <Button type="button" variant="glass" disabled={!notificationsEnabled || isSavingSubscription || isSendingTestNotification} onClick={sendTestNotification}>
                <BellRing className="size-4" />
                {isSendingTestNotification ? t("settings.notifications.sendingTest") : t("settings.notifications.sendTest")}
              </Button>
            </div>

            <p className="mt-4 text-xs leading-5 text-muted">{t("settings.notifications.implementationNote")}</p>
          </div>
        </div>
      </Card>
    </div>
  );
}
