import { useCallback, useEffect, useRef, useState } from "react";
import { useNavigate } from "react-router-dom";
import { useData, useRepos } from "../../data/DataContext";
import { useJobLive } from "../../data/JobLiveContext";
import type { AppNotification } from "../../domain/types";
import { useI18n } from "../../i18n/I18nContext";
import { pathForNotification } from "../../lib/nav";
import { formatLocalDateTime, formatTimeAgo } from "../../lib/time";
import { Button } from "../ui";

const PREVIEW = 5;

function kindLabel(kind: AppNotification["kind"], t: (k: string) => string): string {
  if (kind === "job") return t("nav.jobs");
  if (kind === "outbox") return t("nav.outbox");
  return t("nav.settings");
}

export function BellMenu() {
  const repos = useRepos();
  const { refresh, tick } = useData();
  const { revision, activeJobs } = useJobLive();
  const { t } = useI18n();
  const navigate = useNavigate();
  const [open, setOpen] = useState(false);
  const [items, setItems] = useState<AppNotification[]>([]);
  const [unread, setUnread] = useState(0);
  const rootRef = useRef<HTMLDivElement>(null);

  const loadNotifs = useCallback(async () => {
    try {
      const list = await repos.notifications.list();
      // 未讀優先，再依時間
      const sorted = list.slice().sort((a, b) => {
        const ar = a.read_at ? 1 : 0;
        const br = b.read_at ? 1 : 0;
        if (ar !== br) return ar - br;
        return b.created_at - a.created_at;
      });
      setItems(sorted);
      setUnread(await repos.notifications.unreadCount());
    } catch {
      /* ignore */
    }
  }, [repos.notifications]);

  // tick / job revision / 面板開啟 → 立刻刷新
  useEffect(() => {
    void loadNotifs();
  }, [loadNotifs, tick, revision, open]);

  // 有進行中任務時加速輪詢通知（進度 upsert 會改 title/body）
  useEffect(() => {
    const ms = activeJobs.length > 0 || open ? 2000 : 8000;
    const id = window.setInterval(() => {
      void loadNotifs();
    }, ms);
    return () => window.clearInterval(id);
  }, [activeJobs.length, open, loadNotifs]);

  useEffect(() => {
    const onStore = () => refresh();
    window.addEventListener("harbor:store", onStore);
    return () => window.removeEventListener("harbor:store", onStore);
  }, [refresh]);

  useEffect(() => {
    function onDoc(e: MouseEvent) {
      if (!rootRef.current?.contains(e.target as Node)) setOpen(false);
    }
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, []);

  async function openItem(n: AppNotification) {
    await repos.notifications.markRead(n.id);
    refresh();
    setOpen(false);
    navigate(pathForNotification(n));
  }

  const preview = items.slice(0, PREVIEW);
  const more = Math.max(0, items.length - PREVIEW);

  return (
    <div className="hb-bell" ref={rootRef}>
      <button
        type="button"
        className={`hb-bell__trigger${open ? " is-open" : ""}${unread > 0 ? " has-unread" : ""}`}
        onClick={() => setOpen((v) => !v)}
        aria-expanded={open}
        aria-haspopup="menu"
        aria-label={
          unread > 0 ? `${t("topbar.notifications")}, ${t("topbar.unread", { n: unread })}` : t("topbar.notifications")
        }
        title={t("topbar.notifications")}
      >
        <span className="hb-bell__icon" aria-hidden>
          {/* 簡化鈴鐺：幾何，不用 emoji */}
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none">
            <path
              d="M6 9.5a6 6 0 1 1 12 0c0 3.2 1.2 4.6 1.8 5.2H4.2C4.8 14.1 6 12.7 6 9.5Z"
              stroke="currentColor"
              strokeWidth="1.75"
              strokeLinejoin="round"
            />
            <path
              d="M10 18.2a2 2 0 0 0 4 0"
              stroke="currentColor"
              strokeWidth="1.75"
              strokeLinecap="round"
            />
          </svg>
        </span>
        {unread > 0 ? (
          <span className="hb-bell__badge">{unread > 9 ? "9+" : unread}</span>
        ) : null}
      </button>

      {open ? (
        <div className="hb-bell__panel" role="menu">
          <div className="hb-bell__head">
            <div className="hb-bell__head-title">
              <strong>{t("topbar.notifications")}</strong>
              {unread > 0 ? (
                <span className="hb-bell__head-count">
                  {t("topbar.unread", { n: unread })}
                </span>
              ) : null}
            </div>
            {items.length > 0 ? (
              <button
                type="button"
                className="hb-bell__text-btn"
                onClick={() => {
                  void repos.notifications.markAllRead().then(() => refresh());
                }}
              >
                {t("topbar.markAllRead")}
              </button>
            ) : null}
          </div>

          {items.length === 0 ? (
            <p className="hb-bell__empty">{t("topbar.noNotifications")}</p>
          ) : (
            <ul className="hb-bell__list">
              {preview.map((n) => (
                <li key={n.id}>
                  <button
                    type="button"
                    className={`hb-bell__item${!n.read_at ? " is-unread" : ""}`}
                    onClick={() => void openItem(n)}
                  >
                    <span className="hb-bell__item-top">
                      <span className="hb-bell__kind">{kindLabel(n.kind, t)}</span>
                      <span className="hb-bell__time" title={formatLocalDateTime(n.created_at)}>
                        {formatTimeAgo(n.created_at)}
                      </span>
                    </span>
                    <strong className="hb-bell__item-title">{n.title}</strong>
                    {n.body ? <span className="hb-bell__item-body">{n.body}</span> : null}
                  </button>
                </li>
              ))}
            </ul>
          )}

          <div className="hb-bell__foot">
            {more > 0 ? (
              <span className="text-muted hb-bell__more">
                {t("topbar.moreOlder", { n: more })}
              </span>
            ) : (
              <span />
            )}
            <Button
              type="button"
              variant="ghost"
              onClick={() => {
                setOpen(false);
                navigate("/app/jobs");
              }}
            >
              {t("topbar.jobsCenter")}
            </Button>
          </div>
        </div>
      ) : null}
    </div>
  );
}
