"use client";

import { useState, useEffect, useRef } from "react";
import { useQuery, useMutation, useQueries } from "@tanstack/react-query";
import {
  Bell, Rss, CheckCircle, Copy, RefreshCw, XCircle,
  FlaskConical, Clock, Calendar, FileText, AlertTriangle, Filter, X,
  Mail, Send, MessageSquare,
} from "lucide-react";
import Link from "next/link";
import { notificationsAPI, membersAPI, type NotificationTestResult } from "@/lib/api";
import { useFollows } from "@/lib/hooks/useFollows";
import type { NotificationEvent } from "@/lib/types";

const AUTH_METHODS = [
  { value: "none", label: "No authentication", hint: "Public ntfy.sh topics or open self-hosted servers" },
  { value: "token", label: "Access token", hint: "ntfy token (tk_...)" },
  { value: "basic", label: "Username & password", hint: "For servers behind HTTP basic auth or nginx ACL" },
];

const HOURS = Array.from({ length: 24 }, (_, i) => {
  const period = i < 12 ? "AM" : "PM";
  const hour = i === 0 ? 12 : i > 12 ? i - 12 : i;
  return { value: i, label: `${hour}:00 ${period}` };
});

const EVENT_META: Record<string, { label: string; icon: typeof Bell; color: string }> = {
  new_document: { label: "New Bill Text", icon: FileText, color: "text-blue-500" },
  new_amendment: { label: "Amendment Filed", icon: FileText, color: "text-purple-500" },
  bill_updated: { label: "Bill Updated", icon: AlertTriangle, color: "text-orange-500" },
};

const FILTER_ROWS = [
  { key: "new_document",     label: "New bill text",       hint: "The full text of the bill is published" },
  { key: "new_amendment",    label: "Amendment filed",     hint: "An amendment is filed against the bill" },
  { key: "vote",             label: "Chamber votes",       hint: "Bill passes or fails a House or Senate vote" },
  { key: "presidential",     label: "Presidential action", hint: "Signed into law, vetoed, or enacted" },
  { key: "committee_report", label: "Committee report",    hint: "Committee votes to advance or kill the bill" },
  { key: "calendar",         label: "Calendar placement",  hint: "Scheduled for floor consideration" },
  { key: "procedural",       label: "Procedural",          hint: "Senate cloture votes; conference committee activity" },
  { key: "referral",         label: "Committee referral",  hint: "Bill assigned to a committee — first step for almost every bill" },
] as const;

const MILESTONE_KEYS = ["vote", "presidential", "committee_report", "calendar", "procedural"] as const;

const ALL_OFF = Object.fromEntries(FILTER_ROWS.map((r) => [r.key, false]));

const MODES = [
  {
    key: "neutral",
    label: "Follow",
    description: "Bills you follow in standard mode",
    preset: { new_document: true,  new_amendment: true,  vote: true,  presidential: true,  committee_report: true,  calendar: false, procedural: false, referral: false },
  },
  {
    key: "pocket_veto",
    label: "Pocket Veto",
    description: "Bills you're watching to oppose",
    preset: { new_document: false, new_amendment: false, vote: true,  presidential: true,  committee_report: false, calendar: false, procedural: false, referral: false },
  },
  {
    key: "pocket_boost",
    label: "Pocket Boost",
    description: "Bills you're actively supporting",
    preset: { new_document: true,  new_amendment: true,  vote: true,  presidential: true,  committee_report: true,  calendar: true,  procedural: true,  referral: true  },
  },
] as const;

type ModeKey = "neutral" | "pocket_veto" | "pocket_boost";
type DiscoverySourceKey = "member_follow" | "topic_follow";
type FilterTabKey = ModeKey | "discovery";

const DISCOVERY_SOURCES = [
  {
    key: "member_follow" as DiscoverySourceKey,
    label: "Member Follows",
    description: "Bills sponsored by members you follow",
    preset: { new_document: false, new_amendment: false, vote: true, presidential: true,
              committee_report: true, calendar: false, procedural: false, referral: false },
  },
  {
    key: "topic_follow" as DiscoverySourceKey,
    label: "Topic Follows",
    description: "Bills matching topics you follow",
    preset: { new_document: false, new_amendment: false, vote: true, presidential: true,
              committee_report: false, calendar: false, procedural: false, referral: false },
  },
] as const;

function ModeFilterSection({
  preset,
  filters,
  onChange,
}: {
  preset: Record<string, boolean>;
  filters: Record<string, boolean | string[]>;
  onChange: (f: Record<string, boolean | string[]>) => void;
}) {
  const milestoneCheckRef = useRef<HTMLInputElement>(null);
  const on = MILESTONE_KEYS.filter((k) => filters[k]);
  const milestoneState = on.length === 0 ? "off" : on.length === MILESTONE_KEYS.length ? "on" : "indeterminate";

  useEffect(() => {
    if (milestoneCheckRef.current) {
      milestoneCheckRef.current.indeterminate = milestoneState === "indeterminate";
    }
  }, [milestoneState]);

  const toggleMilestones = () => {
    const val = milestoneState !== "on";
    onChange({ ...filters, ...Object.fromEntries(MILESTONE_KEYS.map((k) => [k, val])) });
  };

  return (
    <div className="space-y-1">
      <div className="flex justify-end mb-1">
        <button
          onClick={() => onChange({ ...ALL_OFF, ...preset })}
          className="bg-muted hover:bg-accent text-xs px-2 py-1 rounded transition-colors"
        >
          Load defaults
        </button>
      </div>

      <label className="flex items-start gap-3 py-1.5 cursor-pointer">
        <input type="checkbox" checked={!!filters["new_document"]}
          onChange={(e) => onChange({ ...filters, new_document: e.target.checked })}
          className="mt-0.5 rounded" />
        <div><span className="text-sm">New bill text</span><span className="text-xs text-muted-foreground ml-2">The full text of the bill is published</span></div>
      </label>

      <label className="flex items-start gap-3 py-1.5 cursor-pointer">
        <input type="checkbox" checked={!!filters["new_amendment"]}
          onChange={(e) => onChange({ ...filters, new_amendment: e.target.checked })}
          className="mt-0.5 rounded" />
        <div><span className="text-sm">Amendment filed</span><span className="text-xs text-muted-foreground ml-2">An amendment is filed against the bill</span></div>
      </label>

      <div className="py-1.5">
        <label className="flex items-start gap-3 cursor-pointer">
          <input ref={milestoneCheckRef} type="checkbox" checked={milestoneState === "on"}
            onChange={toggleMilestones} className="mt-0.5 rounded" />
          <div><span className="text-sm font-medium">Milestones</span><span className="text-xs text-muted-foreground ml-2">Select all milestone types</span></div>
        </label>
        <div className="ml-6 mt-1 space-y-0.5">
          {(["vote", "presidential", "committee_report", "calendar", "procedural"] as const).map((k) => {
            const row = FILTER_ROWS.find((r) => r.key === k)!;
            return (
              <label key={k} className="flex items-start gap-3 py-1 cursor-pointer">
                <input type="checkbox" checked={!!filters[k]}
                  onChange={(e) => onChange({ ...filters, [k]: e.target.checked })}
                  className="mt-0.5 rounded" />
                <div><span className="text-sm">{row.label}</span><span className="text-xs text-muted-foreground ml-2">{row.hint}</span></div>
              </label>
            );
          })}
        </div>
      </div>

      <label className="flex items-start gap-3 py-1.5 cursor-pointer">
        <input type="checkbox" checked={!!filters["referral"]}
          onChange={(e) => onChange({ ...filters, referral: e.target.checked })}
          className="mt-0.5 rounded" />
        <div><span className="text-sm">Committee referral</span><span className="text-xs text-muted-foreground ml-2">Bill assigned to a committee — first step for almost every bill</span></div>
      </label>
    </div>
  );
}

function timeAgo(iso: string) {
  const diff = Date.now() - new Date(iso).getTime();
  const m = Math.floor(diff / 60000);
  if (m < 1) return "just now";
  if (m < 60) return `${m}m ago`;
  const h = Math.floor(m / 60);
  if (h < 24) return `${h}h ago`;
  return `${Math.floor(h / 24)}d ago`;
}

export default function NotificationsPage() {
  const { data: settings, refetch } = useQuery({
    queryKey: ["notification-settings"],
    queryFn: () => notificationsAPI.getSettings(),
  });

  const { data: history = [], isLoading: historyLoading } = useQuery({
    queryKey: ["notification-history"],
    queryFn: () => notificationsAPI.getHistory(),
    staleTime: 60 * 1000,
  });

  const { data: follows = [] } = useFollows();
  const directlyFollowedBillIds = new Set(
    follows.filter((f) => f.follow_type === "bill").map((f) => f.follow_value)
  );

  const update = useMutation({
    mutationFn: (data: Parameters<typeof notificationsAPI.updateSettings>[0]) =>
      notificationsAPI.updateSettings(data),
    onSuccess: () => refetch(),
  });

  const resetRss = useMutation({
    mutationFn: () => notificationsAPI.resetRssToken(),
    onSuccess: () => refetch(),
  });

  // Channel tab
  const [activeChannelTab, setActiveChannelTab] = useState<"ntfy" | "email" | "telegram" | "discord">("ntfy");

  // ntfy form state
  const [topicUrl, setTopicUrl] = useState("");
  const [authMethod, setAuthMethod] = useState("none");
  const [token, setToken] = useState("");
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const [ntfySaved, setNtfySaved] = useState(false);

  // Email form state
  const [emailAddress, setEmailAddress] = useState("");
  const [emailEnabled, setEmailEnabled] = useState(false);
  const [emailSaved, setEmailSaved] = useState(false);
  const [emailTesting, setEmailTesting] = useState(false);
  const [emailTestResult, setEmailTestResult] = useState<NotificationTestResult | null>(null);

  // Test state
  const [ntfyTesting, setNtfyTesting] = useState(false);
  const [ntfyTestResult, setNtfyTestResult] = useState<NotificationTestResult | null>(null);
  const [rssTesting, setRssTesting] = useState(false);
  const [rssTestResult, setRssTestResult] = useState<NotificationTestResult | null>(null);

  // RSS state
  const [rssSaved, setRssSaved] = useState(false);
  const [copied, setCopied] = useState(false);

  // Quiet hours state
  const [quietEnabled, setQuietEnabled] = useState(false);
  const [quietStart, setQuietStart] = useState(22);
  const [quietEnd, setQuietEnd] = useState(8);
  const [quietSaved, setQuietSaved] = useState(false);
  const [detectedTimezone, setDetectedTimezone] = useState<string>("");
  const [savedTimezone, setSavedTimezone] = useState<string | null>(null);

  // Digest state
  const [digestEnabled, setDigestEnabled] = useState(false);
  const [digestFrequency, setDigestFrequency] = useState<"daily" | "weekly">("daily");
  const [digestSaved, setDigestSaved] = useState(false);

  // Alert filter state — one set of 8 filters per follow mode
  const [alertFilters, setAlertFilters] = useState<Record<ModeKey, Record<string, boolean | string[]>>>({
    neutral:      { ...ALL_OFF, ...MODES[0].preset },
    pocket_veto:  { ...ALL_OFF, ...MODES[1].preset },
    pocket_boost: { ...ALL_OFF, ...MODES[2].preset },
  });
  const [discoveryFilters, setDiscoveryFilters] = useState<Record<DiscoverySourceKey, Record<string, boolean | string[]>>>({
    member_follow: { enabled: true, ...DISCOVERY_SOURCES[0].preset },
    topic_follow:  { enabled: true, ...DISCOVERY_SOURCES[1].preset },
  });
  const [activeFilterTab, setActiveFilterTab] = useState<FilterTabKey>("neutral");
  const [filtersSaved, setFiltersSaved] = useState(false);

  // Per-entity mute lists for Discovery — plain arrays; names resolved from memberById at render time
  const [mutedMemberIds, setMutedMemberIds] = useState<string[]>([]);
  const [mutedTopicTags, setMutedTopicTags] = useState<string[]>([]);

  // Derive member/topic follows for the mute dropdowns
  const memberFollows = follows.filter((f) => f.follow_type === "member");
  const topicFollows  = follows.filter((f) => f.follow_type === "topic");

  // Batch-fetch member names so the "Mute a member…" dropdown shows real names
  const memberQueries = useQueries({
    queries: memberFollows.map((f) => ({
      queryKey: ["member", f.follow_value],
      queryFn: () => membersAPI.get(f.follow_value),
      staleTime: 5 * 60 * 1000,
    })),
  });
  const memberById: Record<string, string> = Object.fromEntries(
    memberFollows
      .map((f, i) => [f.follow_value, memberQueries[i]?.data?.name])
      .filter(([, name]) => name)
  );

  // Detect the browser's local timezone once on mount
  useEffect(() => {
    try {
      setDetectedTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone);
    } catch {
      // very old browser — leave empty, dispatcher will fall back to UTC
    }
  }, []);

  // Populate from loaded settings
  useEffect(() => {
    if (!settings) return;
    setTopicUrl(settings.ntfy_topic_url ?? "");
    setAuthMethod(settings.ntfy_auth_method ?? "none");
    setToken(settings.ntfy_token ?? "");
    setUsername(settings.ntfy_username ?? "");
    setPassword(settings.ntfy_password ?? "");
    setEmailAddress(settings.email_address ?? "");
    setEmailEnabled(settings.email_enabled ?? false);
    setDigestEnabled(settings.digest_enabled ?? false);
    setDigestFrequency(settings.digest_frequency ?? "daily");
    setSavedTimezone(settings.timezone ?? null);
    if (settings.quiet_hours_start != null) {
      setQuietEnabled(true);
      setQuietStart(settings.quiet_hours_start);
      setQuietEnd(settings.quiet_hours_end ?? 8);
    } else {
      setQuietEnabled(false);
    }
    if (settings.alert_filters) {
      const af = settings.alert_filters as Record<string, Record<string, boolean>>;
      setAlertFilters({
        neutral:      { ...ALL_OFF, ...MODES[0].preset, ...(af.neutral      || {}) },
        pocket_veto:  { ...ALL_OFF, ...MODES[1].preset, ...(af.pocket_veto  || {}) },
        pocket_boost: { ...ALL_OFF, ...MODES[2].preset, ...(af.pocket_boost || {}) },
      });
      setDiscoveryFilters({
        member_follow: { enabled: true, ...DISCOVERY_SOURCES[0].preset, ...(af.member_follow || {}) },
        topic_follow:  { enabled: true, ...DISCOVERY_SOURCES[1].preset, ...(af.topic_follow  || {}) },
      });
      setMutedMemberIds(((af.member_follow as Record<string, unknown>)?.muted_ids  as string[]) || []);
      setMutedTopicTags(((af.topic_follow  as Record<string, unknown>)?.muted_tags as string[]) || []);
    }
  }, [settings]);

  const saveNtfy = (enabled: boolean) => {
    update.mutate(
      {
        ntfy_topic_url: topicUrl,
        ntfy_auth_method: authMethod,
        ntfy_token: authMethod === "token" ? token : "",
        ntfy_username: authMethod === "basic" ? username : "",
        ntfy_password: authMethod === "basic" ? password : "",
        ntfy_enabled: enabled,
      },
      { onSuccess: () => { setNtfySaved(true); setTimeout(() => setNtfySaved(false), 2000); } }
    );
  };

  const saveEmail = (enabled: boolean) => {
    update.mutate(
      { email_address: emailAddress, email_enabled: enabled },
      { onSuccess: () => { setEmailSaved(true); setTimeout(() => setEmailSaved(false), 2000); } }
    );
  };

  const testEmailFn = async () => {
    setEmailTesting(true);
    setEmailTestResult(null);
    try {
      const result = await notificationsAPI.testEmail();
      setEmailTestResult(result);
    } catch (e: unknown) {
      const detail =
        (e as { response?: { data?: { detail?: string } } })?.response?.data?.detail
        ?? (e instanceof Error ? e.message : "Request failed");
      setEmailTestResult({ status: "error", detail });
    } finally {
      setEmailTesting(false);
    }
  };

  const toggleRss = (enabled: boolean) => {
    update.mutate(
      { rss_enabled: enabled },
      { onSuccess: () => { setRssSaved(true); setTimeout(() => setRssSaved(false), 2000); } }
    );
  };

  const saveQuietHours = () => {
    const onSuccess = () => { setQuietSaved(true); setTimeout(() => setQuietSaved(false), 2000); };
    if (quietEnabled) {
      update.mutate(
        {
          quiet_hours_start: quietStart,
          quiet_hours_end: quietEnd,
          // Include the detected timezone so the dispatcher knows which local time to compare
          ...(detectedTimezone ? { timezone: detectedTimezone } : {}),
        },
        { onSuccess }
      );
    } else {
      // -1 signals the backend to clear quiet hours + timezone
      update.mutate({ quiet_hours_start: -1 }, { onSuccess });
    }
  };

  const saveDigest = () => {
    update.mutate(
      { digest_enabled: digestEnabled, digest_frequency: digestFrequency },
      { onSuccess: () => { setDigestSaved(true); setTimeout(() => setDigestSaved(false), 2000); } }
    );
  };

  const saveAlertFilters = () => {
    update.mutate(
      { alert_filters: {
          ...alertFilters,
          member_follow: { ...discoveryFilters.member_follow, muted_ids: mutedMemberIds },
          topic_follow:  { ...discoveryFilters.topic_follow,  muted_tags: mutedTopicTags },
        } },
      { onSuccess: () => { setFiltersSaved(true); setTimeout(() => setFiltersSaved(false), 2000); } }
    );
  };

  const testNtfy = async () => {
    setNtfyTesting(true);
    setNtfyTestResult(null);
    try {
      const result = await notificationsAPI.testNtfy({
        ntfy_topic_url: topicUrl,
        ntfy_auth_method: authMethod,
        ntfy_token: authMethod === "token" ? token : "",
        ntfy_username: authMethod === "basic" ? username : "",
        ntfy_password: authMethod === "basic" ? password : "",
      });
      setNtfyTestResult(result);
    } catch (e: unknown) {
      const detail =
        (e as { response?: { data?: { detail?: string } } })?.response?.data?.detail
        ?? (e instanceof Error ? e.message : "Request failed");
      setNtfyTestResult({ status: "error", detail });
    } finally {
      setNtfyTesting(false);
    }
  };

  const testRss = async () => {
    setRssTesting(true);
    setRssTestResult(null);
    try {
      const result = await notificationsAPI.testRss();
      setRssTestResult(result);
    } catch (e: unknown) {
      const detail =
        (e as { response?: { data?: { detail?: string } } })?.response?.data?.detail
        ?? (e instanceof Error ? e.message : "Feed check failed");
      setRssTestResult({ status: "error", detail });
    } finally {
      setRssTesting(false);
    }
  };

  const rssUrl = settings?.rss_token
    ? `${typeof window !== "undefined" ? window.location.origin : ""}/api/notifications/feed/${settings.rss_token}.xml`
    : null;

  const ResultBadge = ({ result }: { result: NotificationTestResult }) => (
    <div className={`flex items-start gap-2 text-xs rounded-md px-3 py-2 ${
      result.status === "ok"
        ? "bg-green-50 dark:bg-green-900/20 text-green-700 dark:text-green-400"
        : "bg-red-50 dark:bg-red-900/20 text-red-700 dark:text-red-400"
    }`}>
      {result.status === "ok"
        ? <CheckCircle className="w-3.5 h-3.5 mt-0.5 shrink-0" />
        : <XCircle className="w-3.5 h-3.5 mt-0.5 shrink-0" />}
      {result.detail}
    </div>
  );

  return (
    <div className="space-y-8 max-w-2xl">
      <div>
        <h1 className="text-2xl font-bold flex items-center gap-2">
          <Bell className="w-5 h-5" /> Notifications
        </h1>
        <p className="text-muted-foreground text-sm mt-1">
          Get alerted when bills you follow are updated, new text is published, or amendments are filed.
        </p>
      </div>

      {/* Notification Channels */}
      <section className="bg-card border border-border rounded-lg p-6 space-y-5">
        <div>
          <h2 className="font-semibold flex items-center gap-2">
            <Bell className="w-4 h-4" /> Notification Channels
          </h2>
          <p className="text-xs text-muted-foreground mt-1">
            Configure where you receive push notifications. Enable one or more channels.
          </p>
        </div>

        {/* Channel tab bar */}
        <div className="flex gap-0 border-b border-border -mx-6 px-6">
          {([
            { key: "ntfy", label: "ntfy", icon: Bell, active: settings?.ntfy_enabled },
            { key: "email", label: "Email", icon: Mail, active: settings?.email_enabled },
            { key: "telegram", label: "Telegram", icon: Send, active: false },
            { key: "discord", label: "Discord", icon: MessageSquare, active: false },
          ] as const).map(({ key, label, icon: Icon, active }) => (
            <button
              key={key}
              onClick={() => setActiveChannelTab(key)}
              className={`flex items-center gap-1.5 px-4 py-2 text-sm font-medium transition-colors border-b-2 -mb-px ${
                activeChannelTab === key
                  ? "border-primary text-foreground"
                  : "border-transparent text-muted-foreground hover:text-foreground"
              }`}
            >
              <Icon className="w-3.5 h-3.5" />
              {label}
              {active && <span className="w-1.5 h-1.5 rounded-full bg-green-500 ml-0.5" />}
            </button>
          ))}
        </div>

        {/* ntfy tab */}
        {activeChannelTab === "ntfy" && (
          <div className="space-y-5">
            <p className="text-xs text-muted-foreground">
              Uses <a href="https://ntfy.sh" target="_blank" rel="noopener noreferrer" className="text-primary hover:underline">ntfy</a> — a free, open-source push notification service.
              Use the public <code className="bg-muted px-1 rounded">ntfy.sh</code> server or your own self-hosted instance.
            </p>

            <div className="space-y-1.5">
              <label className="text-sm font-medium">Topic URL</label>
              <p className="text-xs text-muted-foreground">
                The full URL to your ntfy topic, e.g.{" "}
                <code className="bg-muted px-1 rounded">https://ntfy.sh/my-pocketveto-alerts</code>
              </p>
              <input
                type="url"
                placeholder="https://ntfy.sh/your-topic"
                value={topicUrl}
                onChange={(e) => setTopicUrl(e.target.value)}
                className="w-full px-3 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-1 focus:ring-primary"
              />
            </div>

            <div className="space-y-2">
              <label className="text-sm font-medium">Authentication</label>
              <div className="space-y-2">
                {AUTH_METHODS.map(({ value, label, hint }) => (
                  <label key={value} className="flex items-start gap-3 cursor-pointer">
                    <input type="radio" name="ntfy-auth" value={value} checked={authMethod === value}
                      onChange={() => setAuthMethod(value)} className="mt-0.5" />
                    <div>
                      <div className="text-sm font-medium">{label}</div>
                      <div className="text-xs text-muted-foreground">{hint}</div>
                    </div>
                  </label>
                ))}
              </div>
            </div>

            {authMethod === "token" && (
              <div className="space-y-1.5">
                <label className="text-sm font-medium">Access Token</label>
                <input type="password" placeholder="tk_..." value={token}
                  onChange={(e) => setToken(e.target.value)}
                  className="w-full px-3 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-1 focus:ring-primary" />
              </div>
            )}

            {authMethod === "basic" && (
              <div className="space-y-3">
                <div className="space-y-1.5">
                  <label className="text-sm font-medium">Username</label>
                  <input type="text" placeholder="your-username" value={username}
                    onChange={(e) => setUsername(e.target.value)}
                    className="w-full px-3 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-1 focus:ring-primary" />
                </div>
                <div className="space-y-1.5">
                  <label className="text-sm font-medium">Password</label>
                  <input type="password" placeholder="your-password" value={password}
                    onChange={(e) => setPassword(e.target.value)}
                    className="w-full px-3 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-1 focus:ring-primary" />
                </div>
              </div>
            )}

            <div className="space-y-3 pt-1 border-t border-border">
              <div className="flex items-center gap-3">
                <button onClick={() => saveNtfy(true)} disabled={!topicUrl.trim() || update.isPending}
                  className="flex items-center gap-2 px-4 py-2 text-sm bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 transition-colors">
                  {ntfySaved ? <CheckCircle className="w-3.5 h-3.5" /> : <Bell className="w-3.5 h-3.5" />}
                  {ntfySaved ? "Saved!" : "Save & Enable"}
                </button>
                <button onClick={testNtfy} disabled={!topicUrl.trim() || ntfyTesting}
                  className="flex items-center gap-2 px-4 py-2 text-sm bg-muted hover:bg-accent rounded-md disabled:opacity-50 transition-colors">
                  {ntfyTesting ? <RefreshCw className="w-3.5 h-3.5 animate-spin" /> : <FlaskConical className="w-3.5 h-3.5" />}
                  {ntfyTesting ? "Sending…" : "Test"}
                </button>
                {settings?.ntfy_enabled && (
                  <button onClick={() => saveNtfy(false)} disabled={update.isPending}
                    className="text-xs text-muted-foreground hover:text-foreground transition-colors">
                    Disable
                  </button>
                )}
              </div>
              {ntfyTestResult && <ResultBadge result={ntfyTestResult} />}
            </div>
          </div>
        )}

        {/* Email tab */}
        {activeChannelTab === "email" && (
          <div className="space-y-5">
            <p className="text-xs text-muted-foreground">
              Receive bill alerts as plain-text emails. Requires SMTP to be configured on the server (see <code className="bg-muted px-1 rounded">.env</code>).
            </p>

            <div className="space-y-1.5">
              <label className="text-sm font-medium">Delivery Address</label>
              <p className="text-xs text-muted-foreground">The email address to send alerts to.</p>
              <input
                type="email"
                placeholder="you@example.com"
                value={emailAddress}
                onChange={(e) => setEmailAddress(e.target.value)}
                className="w-full px-3 py-2 text-sm bg-background border border-border rounded-md focus:outline-none focus:ring-1 focus:ring-primary"
              />
            </div>

            <div className="space-y-3 pt-1 border-t border-border">
              <div className="flex items-center gap-3">
                <button onClick={() => saveEmail(true)} disabled={!emailAddress.trim() || update.isPending}
                  className="flex items-center gap-2 px-4 py-2 text-sm bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 transition-colors">
                  {emailSaved ? <CheckCircle className="w-3.5 h-3.5" /> : <Mail className="w-3.5 h-3.5" />}
                  {emailSaved ? "Saved!" : "Save & Enable"}
                </button>
                <button onClick={testEmailFn} disabled={!emailAddress.trim() || emailTesting}
                  className="flex items-center gap-2 px-4 py-2 text-sm bg-muted hover:bg-accent rounded-md disabled:opacity-50 transition-colors">
                  {emailTesting ? <RefreshCw className="w-3.5 h-3.5 animate-spin" /> : <FlaskConical className="w-3.5 h-3.5" />}
                  {emailTesting ? "Sending…" : "Test"}
                </button>
                {settings?.email_enabled && (
                  <button onClick={() => saveEmail(false)} disabled={update.isPending}
                    className="text-xs text-muted-foreground hover:text-foreground transition-colors">
                    Disable
                  </button>
                )}
              </div>
              {emailTestResult && <ResultBadge result={emailTestResult} />}
            </div>
          </div>
        )}

        {/* Telegram tab — coming soon */}
        {activeChannelTab === "telegram" && (
          <div className="flex flex-col items-center justify-center py-10 space-y-4 text-center">
            <div className="w-14 h-14 rounded-full bg-muted flex items-center justify-center">
              <Send className="w-6 h-6 text-muted-foreground" />
            </div>
            <div className="space-y-1.5">
              <p className="font-medium">Telegram Notifications</p>
              <p className="text-sm text-muted-foreground max-w-xs leading-relaxed">
                Receive PocketVeto alerts directly in Telegram via a dedicated bot.
                Will require a Telegram Bot Token and your Chat ID.
              </p>
            </div>
            <span className="text-xs px-3 py-1 bg-muted rounded-full text-muted-foreground font-medium">Coming soon</span>
          </div>
        )}

        {/* Discord tab — coming soon */}
        {activeChannelTab === "discord" && (
          <div className="flex flex-col items-center justify-center py-10 space-y-4 text-center">
            <div className="w-14 h-14 rounded-full bg-muted flex items-center justify-center">
              <MessageSquare className="w-6 h-6 text-muted-foreground" />
            </div>
            <div className="space-y-1.5">
              <p className="font-medium">Discord Notifications</p>
              <p className="text-sm text-muted-foreground max-w-xs leading-relaxed">
                Post bill alerts to a Discord channel via a webhook URL.
                Will support per-channel routing and @role mentions.
              </p>
            </div>
            <span className="text-xs px-3 py-1 bg-muted rounded-full text-muted-foreground font-medium">Coming soon</span>
          </div>
        )}
      </section>

      {/* Alert Filters */}
      <section className="bg-card border border-border rounded-lg p-6 space-y-4">
        <div>
          <h2 className="font-semibold flex items-center gap-2">
            <Filter className="w-4 h-4" /> Alert Filters
          </h2>
          <p className="text-xs text-muted-foreground mt-1">
            Each follow mode has its own independent filter set. "Load defaults" resets that mode to its recommended starting point.
          </p>
        </div>

        {/* Tab bar */}
        <div className="flex gap-0 border-b border-border">
          {MODES.map((mode) => (
            <button
              key={mode.key}
              onClick={() => setActiveFilterTab(mode.key as ModeKey)}
              className={`px-4 py-2 text-sm font-medium transition-colors border-b-2 -mb-px ${
                activeFilterTab === mode.key
                  ? "border-primary text-foreground"
                  : "border-transparent text-muted-foreground hover:text-foreground"
              }`}
            >
              {mode.label}
            </button>
          ))}
          <button
            onClick={() => setActiveFilterTab("discovery")}
            className={`px-4 py-2 text-sm font-medium transition-colors border-b-2 -mb-px ${
              activeFilterTab === "discovery"
                ? "border-primary text-foreground"
                : "border-transparent text-muted-foreground hover:text-foreground"
            }`}
          >
            Discovery
          </button>
        </div>

        {/* Tab panels */}
        {MODES.map((mode) => activeFilterTab === mode.key && (
          <div key={mode.key} className="space-y-4">
            <ModeFilterSection
              preset={mode.preset}
              filters={alertFilters[mode.key as ModeKey]}
              onChange={(f) => setAlertFilters((prev) => ({ ...prev, [mode.key]: f }))}
            />
            <div className="pt-2 border-t border-border flex justify-end">
              <button
                onClick={saveAlertFilters}
                disabled={update.isPending}
                className="flex items-center gap-2 px-4 py-2 text-sm bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 transition-colors"
              >
                {filtersSaved ? <CheckCircle className="w-3.5 h-3.5" /> : null}
                {filtersSaved ? "Saved!" : `Save ${mode.label} Filters`}
              </button>
            </div>
          </div>
        ))}

        {activeFilterTab === "discovery" && (
          <div className="space-y-6">
            {/* Member follows */}
            {(() => {
              const src = DISCOVERY_SOURCES[0];
              const srcFilters = discoveryFilters[src.key];
              const { enabled, ...alertOnly } = srcFilters;
              const unmutedMembers = memberFollows.filter((f) => !mutedMemberIds.includes(f.follow_value));
              return (
                <div className="space-y-3">
                  <label className="flex items-center gap-3 cursor-pointer">
                    <input type="checkbox" checked={!!enabled}
                      onChange={(e) => setDiscoveryFilters((prev) => ({ ...prev, [src.key]: { ...prev[src.key], enabled: e.target.checked } }))}
                      className="rounded" />
                    <div>
                      <span className="text-sm font-medium">Notify me about bills from member follows</span>
                      <span className="text-xs text-muted-foreground ml-2">{src.description}</span>
                    </div>
                  </label>
                  {!!enabled && (
                    <div className="ml-6 space-y-4">
                      <ModeFilterSection preset={src.preset} filters={alertOnly}
                        onChange={(f) => setDiscoveryFilters((prev) => ({ ...prev, [src.key]: { ...f, enabled: true } }))} />
                      {/* Muted members */}
                      <div className="space-y-2">
                        <p className="text-xs font-medium text-muted-foreground">Muted members</p>
                        <div className="flex flex-wrap gap-1.5">
                          {mutedMemberIds.length === 0 ? (
                            <span className="text-xs text-muted-foreground italic">None — all followed members will trigger notifications</span>
                          ) : mutedMemberIds.map((id) => (
                            <span key={id} className="inline-flex items-center gap-1.5 text-xs border border-border bg-muted rounded-full px-2.5 py-1">
                              <span>{memberById[id] ?? id}</span>
                              <button onClick={() => setMutedMemberIds((prev) => prev.filter((x) => x !== id))}
                                className="text-muted-foreground hover:text-foreground transition-colors leading-none">
                                <X className="w-3 h-3" />
                              </button>
                            </span>
                          ))}
                        </div>
                        {unmutedMembers.length > 0 && (
                          <select value=""
                            onChange={(e) => { const id = e.target.value; if (id) setMutedMemberIds((prev) => [...prev, id]); }}
                            className="text-xs px-2 py-1.5 bg-background border border-border rounded-md">
                            <option value="" disabled>Mute a member…</option>
                            {unmutedMembers.map((f) => (
                              <option key={f.follow_value} value={f.follow_value}>
                                {memberById[f.follow_value] ?? f.follow_value}
                              </option>
                            ))}
                          </select>
                        )}
                      </div>
                    </div>
                  )}
                </div>
              );
            })()}

            <div className="border-t border-border" />

            {/* Topic follows */}
            {(() => {
              const src = DISCOVERY_SOURCES[1];
              const srcFilters = discoveryFilters[src.key];
              const { enabled, ...alertOnly } = srcFilters;
              const unmutedTopics = topicFollows.filter((f) => !mutedTopicTags.includes(f.follow_value));
              return (
                <div className="space-y-3">
                  <label className="flex items-center gap-3 cursor-pointer">
                    <input type="checkbox" checked={!!enabled}
                      onChange={(e) => setDiscoveryFilters((prev) => ({ ...prev, [src.key]: { ...prev[src.key], enabled: e.target.checked } }))}
                      className="rounded" />
                    <div>
                      <span className="text-sm font-medium">Notify me about bills from topic follows</span>
                      <span className="text-xs text-muted-foreground ml-2">{src.description}</span>
                    </div>
                  </label>
                  {!!enabled && (
                    <div className="ml-6 space-y-4">
                      <ModeFilterSection preset={src.preset} filters={alertOnly}
                        onChange={(f) => setDiscoveryFilters((prev) => ({ ...prev, [src.key]: { ...f, enabled: true } }))} />
                      {/* Muted topics */}
                      <div className="space-y-2">
                        <p className="text-xs font-medium text-muted-foreground">Muted topics</p>
                        <div className="flex flex-wrap gap-1.5">
                          {mutedTopicTags.length === 0 ? (
                            <span className="text-xs text-muted-foreground italic">None — all followed topics will trigger notifications</span>
                          ) : mutedTopicTags.map((tag) => (
                            <span key={tag} className="inline-flex items-center gap-1.5 text-xs border border-border bg-muted rounded-full px-2.5 py-1">
                              <span>{tag}</span>
                              <button onClick={() => setMutedTopicTags((prev) => prev.filter((x) => x !== tag))}
                                className="text-muted-foreground hover:text-foreground transition-colors leading-none">
                                <X className="w-3 h-3" />
                              </button>
                            </span>
                          ))}
                        </div>
                        {unmutedTopics.length > 0 && (
                          <select value=""
                            onChange={(e) => { const tag = e.target.value; if (tag) setMutedTopicTags((prev) => [...prev, tag]); }}
                            className="text-xs px-2 py-1.5 bg-background border border-border rounded-md">
                            <option value="" disabled>Mute a topic…</option>
                            {unmutedTopics.map((f) => (
                              <option key={f.follow_value} value={f.follow_value}>{f.follow_value}</option>
                            ))}
                          </select>
                        )}
                      </div>
                    </div>
                  )}
                </div>
              );
            })()}

            <div className="pt-2 border-t border-border flex justify-end">
              <button onClick={saveAlertFilters} disabled={update.isPending}
                className="flex items-center gap-2 px-4 py-2 text-sm bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 transition-colors">
                {filtersSaved ? <CheckCircle className="w-3.5 h-3.5" /> : null}
                {filtersSaved ? "Saved!" : "Save Discovery Filters"}
              </button>
            </div>
          </div>
        )}
      </section>

      {/* Quiet Hours */}
      <section className="bg-card border border-border rounded-lg p-6 space-y-4">
        <div>
          <h2 className="font-semibold flex items-center gap-2">
            <Clock className="w-4 h-4" /> Quiet Hours
          </h2>
          <p className="text-xs text-muted-foreground mt-1">
            Pause ntfy push notifications during set hours. Events accumulate and fire as a batch when quiet hours end.
            RSS is unaffected.
          </p>
        </div>

        <label className="flex items-center gap-3 cursor-pointer">
          <input type="checkbox" checked={quietEnabled} onChange={(e) => setQuietEnabled(e.target.checked)}
            className="rounded" />
          <span className="text-sm font-medium">Enable quiet hours</span>
        </label>

        {quietEnabled && (
          <div className="space-y-3">
            <div className="flex items-center gap-3 flex-wrap">
              <div className="flex items-center gap-2">
                <label className="text-sm text-muted-foreground">From</label>
                <select value={quietStart} onChange={(e) => setQuietStart(Number(e.target.value))}
                  className="px-2 py-1.5 text-sm bg-background border border-border rounded-md">
                  {HOURS.map(({ value, label }) => <option key={value} value={value}>{label}</option>)}
                </select>
              </div>
              <div className="flex items-center gap-2">
                <label className="text-sm text-muted-foreground">To</label>
                <select value={quietEnd} onChange={(e) => setQuietEnd(Number(e.target.value))}
                  className="px-2 py-1.5 text-sm bg-background border border-border rounded-md">
                  {HOURS.map(({ value, label }) => <option key={value} value={value}>{label}</option>)}
                </select>
              </div>
              {quietStart > quietEnd && (
                <span className="text-xs text-muted-foreground">(overnight window)</span>
              )}
            </div>
            {detectedTimezone && (
              <p className="text-xs text-muted-foreground">
                Times are in your local timezone: <span className="font-medium text-foreground">{detectedTimezone}</span>
                {savedTimezone && savedTimezone !== detectedTimezone && (
                  <span className="text-amber-600 dark:text-amber-400"> · saved as {savedTimezone} — save to update</span>
                )}
              </p>
            )}
          </div>
        )}

        <button onClick={saveQuietHours} disabled={update.isPending}
          className="flex items-center gap-2 px-4 py-2 text-sm bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 transition-colors">
          {quietSaved ? <CheckCircle className="w-3.5 h-3.5" /> : null}
          {quietSaved ? "Saved!" : "Save Quiet Hours"}
        </button>
      </section>

      {/* Digest */}
      <section className="bg-card border border-border rounded-lg p-6 space-y-4">
        <div>
          <h2 className="font-semibold flex items-center gap-2">
            <Calendar className="w-4 h-4" /> Digest Mode
          </h2>
          <p className="text-xs text-muted-foreground mt-1">
            Instead of per-event push notifications, receive a single bundled ntfy summary on a schedule.
            RSS feed is always real-time regardless of this setting.
          </p>
        </div>

        <label className="flex items-center gap-3 cursor-pointer">
          <input type="checkbox" checked={digestEnabled} onChange={(e) => setDigestEnabled(e.target.checked)}
            className="rounded" />
          <span className="text-sm font-medium">Enable digest mode</span>
        </label>

        {digestEnabled && (
          <div className="flex items-center gap-3">
            <label className="text-sm text-muted-foreground">Frequency</label>
            <div className="flex gap-3">
              {(["daily", "weekly"] as const).map((freq) => (
                <label key={freq} className="flex items-center gap-2 cursor-pointer">
                  <input type="radio" name="digest-freq" value={freq} checked={digestFrequency === freq}
                    onChange={() => setDigestFrequency(freq)} />
                  <span className="text-sm capitalize">{freq}</span>
                  {freq === "weekly" && <span className="text-xs text-muted-foreground">(Mondays, 8 AM UTC)</span>}
                  {freq === "daily" && <span className="text-xs text-muted-foreground">(8 AM UTC)</span>}
                </label>
              ))}
            </div>
          </div>
        )}

        <button onClick={saveDigest} disabled={update.isPending}
          className="flex items-center gap-2 px-4 py-2 text-sm bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 transition-colors">
          {digestSaved ? <CheckCircle className="w-3.5 h-3.5" /> : null}
          {digestSaved ? "Saved!" : "Save Digest Settings"}
        </button>
      </section>

      {/* RSS */}
      <section className="bg-card border border-border rounded-lg p-6 space-y-4">
        <div className="flex items-start justify-between gap-4">
          <div>
            <h2 className="font-semibold flex items-center gap-2">
              <Rss className="w-4 h-4" /> RSS Feed
            </h2>
            <p className="text-xs text-muted-foreground mt-1">
              A private, tokenized RSS feed of your bill alerts — subscribe in any RSS reader.
              Independent of ntfy; enable either or both.
            </p>
          </div>
          {settings?.rss_enabled && (
            <span className="flex items-center gap-1 text-xs text-green-600 dark:text-green-400 shrink-0">
              <CheckCircle className="w-3.5 h-3.5" /> Active
            </span>
          )}
        </div>

        {rssUrl && (
          <div className="space-y-2">
            <label className="text-xs font-medium text-muted-foreground uppercase tracking-wide">Your feed URL</label>
            <div className="flex items-center gap-2">
              <code className="flex-1 text-xs bg-muted px-2 py-2 rounded truncate">{rssUrl}</code>
              <button onClick={() => { navigator.clipboard.writeText(rssUrl); setCopied(true); setTimeout(() => setCopied(false), 2000); }}
                className="shrink-0 p-1.5 rounded hover:bg-accent transition-colors" title="Copy RSS URL">
                {copied ? <CheckCircle className="w-4 h-4 text-green-500" /> : <Copy className="w-4 h-4 text-muted-foreground" />}
              </button>
            </div>
          </div>
        )}

        <div className="space-y-3 pt-1 border-t border-border">
          <div className="flex items-center gap-3">
            {!settings?.rss_enabled ? (
              <button onClick={() => toggleRss(true)} disabled={update.isPending}
                className="flex items-center gap-2 px-4 py-2 text-sm bg-primary text-primary-foreground rounded-md hover:bg-primary/90 disabled:opacity-50 transition-colors">
                {rssSaved ? <CheckCircle className="w-3.5 h-3.5" /> : <Rss className="w-3.5 h-3.5" />}
                {rssSaved ? "Enabled!" : "Enable RSS"}
              </button>
            ) : (
              <button onClick={() => toggleRss(false)} disabled={update.isPending}
                className="text-xs text-muted-foreground hover:text-foreground transition-colors">
                Disable RSS
              </button>
            )}
            {rssUrl && (
              <>
                <button onClick={testRss} disabled={rssTesting}
                  className="flex items-center gap-2 px-4 py-2 text-sm bg-muted hover:bg-accent rounded-md disabled:opacity-50 transition-colors">
                  {rssTesting ? <RefreshCw className="w-3.5 h-3.5 animate-spin" /> : <FlaskConical className="w-3.5 h-3.5" />}
                  {rssTesting ? "Checking…" : "Test"}
                </button>
                <button onClick={() => resetRss.mutate()} disabled={resetRss.isPending}
                  className="flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors"
                  title="Generate a new URL — old URL will stop working">
                  <RefreshCw className="w-3 h-3" /> Regenerate URL
                </button>
              </>
            )}
          </div>
          {rssTestResult && <ResultBadge result={rssTestResult} />}
        </div>
      </section>

      {/* Notification History */}
      {(() => {
        const directEvents = history.filter((e: NotificationEvent) => {
          const src = (e.payload as Record<string, unknown>)?.source as string | undefined;
          if (src === "topic_follow") return false;
          if (src === "bill_follow" || src === "member_follow") return true;
          // Legacy events (no source field): treat as direct if bill is followed
          return directlyFollowedBillIds.has(e.bill_id);
        });
        const topicEvents = history.filter((e: NotificationEvent) => {
          const src = (e.payload as Record<string, unknown>)?.source as string | undefined;
          if (src === "topic_follow") return true;
          if (src) return false;
          return !directlyFollowedBillIds.has(e.bill_id);
        });

        const EventRow = ({ event, showDispatch }: { event: NotificationEvent; showDispatch: boolean }) => {
          const meta = EVENT_META[event.event_type] ?? { label: "Update", icon: Bell, color: "text-muted-foreground" };
          const Icon = meta.icon;
          const p = (event.payload ?? {}) as Record<string, unknown>;
          const billLabel = p.bill_label as string | undefined;
          const billTitle = p.bill_title as string | undefined;
          const briefSummary = p.brief_summary as string | undefined;
          return (
            <div className="flex items-start gap-3 py-3">
              <Icon className={`w-4 h-4 mt-0.5 shrink-0 ${meta.color}`} />
              <div className="flex-1 min-w-0">
                <div className="flex items-center gap-2 flex-wrap">
                  <span className="text-xs font-medium">{meta.label}</span>
                  {billLabel && (
                    <Link href={`/bills/${event.bill_id}`}
                      className="text-xs font-mono bg-muted px-1.5 py-0.5 rounded hover:text-primary transition-colors">
                      {billLabel}
                    </Link>
                  )}
                  <span className="text-xs text-muted-foreground ml-auto">{timeAgo(event.created_at)}</span>
                </div>
                {billTitle && (
                  <p className="text-xs text-muted-foreground mt-0.5 line-clamp-1">{billTitle}</p>
                )}
                {(() => {
                  const src = p.source as string | undefined;
                  const modeLabels: Record<string, string> = {
                    pocket_veto: "Pocket Veto", pocket_boost: "Pocket Boost", neutral: "Following",
                  };
                  let reason: string | null = null;
                  if (src === "bill_follow") {
                    const mode = p.follow_mode as string | undefined;
                    reason = mode ? `${modeLabels[mode] ?? "Following"} this bill` : null;
                  } else if (src === "member_follow") {
                    const name = p.matched_member_name as string | undefined;
                    reason = name ? `You follow ${name}` : "Member you follow";
                  } else if (src === "topic_follow") {
                    const topic = p.matched_topic as string | undefined;
                    reason = topic ? `You follow "${topic}"` : "Topic you follow";
                  }
                  return reason ? (
                    <p className="text-xs text-muted-foreground mt-0.5 italic">{reason}</p>
                  ) : null;
                })()}
                {briefSummary && (
                  <p className="text-xs text-muted-foreground mt-0.5 line-clamp-2">{briefSummary}</p>
                )}
              </div>
              {showDispatch && (
                <span className={`text-xs shrink-0 ${event.dispatched_at ? "text-green-500" : "text-amber-500"}`}
                  title={event.dispatched_at ? `Sent ${timeAgo(event.dispatched_at)}` : "Pending dispatch"}>
                  {event.dispatched_at ? "✓" : "⏳"}
                </span>
              )}
            </div>
          );
        };

        return (
          <>
            <section className="bg-card border border-border rounded-lg p-6 space-y-4">
              <div>
                <h2 className="font-semibold flex items-center gap-2">
                  <Bell className="w-4 h-4" /> Recent Alerts
                </h2>
                <p className="text-xs text-muted-foreground mt-1">
                  Notifications for bills and members you directly follow. Last 50 events.
                </p>
              </div>
              {historyLoading ? (
                <p className="text-sm text-muted-foreground">Loading history…</p>
              ) : directEvents.length === 0 ? (
                <p className="text-sm text-muted-foreground">
                  No alerts yet. Follow some bills and check back after the next poll.
                </p>
              ) : (
                <div className="divide-y divide-border">
                  {directEvents.map((event: NotificationEvent) => (
                    <EventRow key={event.id} event={event} showDispatch />
                  ))}
                </div>
              )}
            </section>

            {topicEvents.length > 0 && (
              <section className="bg-card border border-border rounded-lg p-6 space-y-4">
                <div>
                  <h2 className="font-semibold flex items-center gap-2">
                    <Bell className="w-4 h-4 text-muted-foreground" /> Based on your topic follows
                  </h2>
                  <p className="text-xs text-muted-foreground mt-1">
                    Bills matching topics you follow that have had recent activity.
                    Milestone events (passed, signed, new text) are pushed; routine referrals are not.
                    Follow a bill directly to get all updates.
                  </p>
                </div>
                <div className="divide-y divide-border">
                  {topicEvents.map((event: NotificationEvent) => (
                    <EventRow key={event.id} event={event} showDispatch />
                  ))}
                </div>
              </section>
            )}
          </>
        );
      })()}
    </div>
  );
}
