import { useEffect, useId, useRef, useState } from "react";
import { NavLink, useLocation, useNavigate } from "react-router-dom";
import { useI18n } from "../../i18n/I18nContext";
import { useFirstRun } from "../../firstRun/FirstRunContext";
import {
  firstRunNavKeys,
  isMoreNavActive,
  isNavActive,
  mobileDockMoreKeys,
  mobileDockPrimaryKeys,
  navGroupedItemsByKeys,
  navItemsByKeys,
} from "../../lib/nav";
import { AppIcon } from "../ui/AppIcons";

export function MobileDock() {
  const { pathname } = useLocation();
  const { t } = useI18n();
  const navigate = useNavigate();
  const { active: firstRun } = useFirstRun();
  const [moreOpen, setMoreOpen] = useState(false);
  const sheetRef = useRef<HTMLDivElement>(null);
  const moreBtnRef = useRef<HTMLButtonElement>(null);
  const titleId = useId();

  const dockItems = navItemsByKeys(firstRun ? firstRunNavKeys : mobileDockPrimaryKeys);
  const moreGroups = firstRun ? [] : navGroupedItemsByKeys(mobileDockMoreKeys);
  const moreActive = !firstRun && isMoreNavActive(pathname);

  useEffect(() => {
    setMoreOpen(false);
  }, [pathname]);

  useEffect(() => {
    if (!moreOpen) return;
    function onKey(e: KeyboardEvent) {
      if (e.key === "Escape") setMoreOpen(false);
    }
    function onDoc(e: MouseEvent | TouchEvent) {
      const node = e.target as Node;
      if (sheetRef.current?.contains(node) || moreBtnRef.current?.contains(node)) return;
      setMoreOpen(false);
    }
    document.addEventListener("keydown", onKey);
    document.addEventListener("mousedown", onDoc);
    document.addEventListener("touchstart", onDoc);
    return () => {
      document.removeEventListener("keydown", onKey);
      document.removeEventListener("mousedown", onDoc);
      document.removeEventListener("touchstart", onDoc);
    };
  }, [moreOpen]);

  useEffect(() => {
    if (!moreOpen) return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    return () => {
      document.body.style.overflow = prev;
    };
  }, [moreOpen]);

  function goMore(path: string) {
    setMoreOpen(false);
    navigate(path);
  }

  return (
    <>
      {moreOpen ? (
        <div className="hb-dock-more" role="presentation">
          <button
            type="button"
            className="hb-dock-more__scrim"
            aria-label={t("common.cancel")}
            onClick={() => setMoreOpen(false)}
          />
          <div
            ref={sheetRef}
            className="hb-dock-more__sheet"
            role="dialog"
            aria-modal="true"
            aria-labelledby={titleId}
          >
            <div className="hb-dock-more__handle" aria-hidden />
            <h2 id={titleId} className="hb-dock-more__title">
              {t("nav.moreTitle")}
            </h2>
            {moreGroups.map(({ group, items }) => (
              <div className="hb-dock-more__group" key={group.key}>
                <p className="hb-dock-more__group-label">{t(group.labelKey)}</p>
                <ul className="hb-dock-more__list">
                  {items.map((item) => {
                    const active = isNavActive(pathname, item);
                    return (
                      <li key={item.key}>
                        <button
                          type="button"
                          className={`hb-dock-more__row${active ? " is-active" : ""}`}
                          onClick={() => goMore(item.path)}
                        >
                          <span className="hb-dock-more__ico">
                            <AppIcon name={item.key} size={20} />
                          </span>
                          <span className="hb-dock-more__row-label">{t(item.labelKey)}</span>
                          {active ? (
                            <span className="hb-dock-more__check" aria-hidden>
                              <AppIcon name="check" size={16} />
                            </span>
                          ) : null}
                        </button>
                      </li>
                    );
                  })}
                </ul>
              </div>
            ))}
          </div>
        </div>
      ) : null}

      <nav className="hb-dock" aria-label={t("nav.navigate")}>
        {dockItems.map((item) => {
          const active = isNavActive(pathname, item);
          return (
            <NavLink
              key={item.key}
              to={item.path}
              className={`hb-dock__item${active ? " hb-dock__item--active" : ""}`}
            >
              <span className="hb-dock__icon">
                <AppIcon name={item.key} size={22} />
              </span>
              <span className="hb-dock__label">{t(item.labelKey)}</span>
            </NavLink>
          );
        })}
        {firstRun ? null : (
        <button
          ref={moreBtnRef}
          type="button"
          className={`hb-dock__item hb-dock__item--btn${moreOpen || moreActive ? " hb-dock__item--active" : ""}`}
          aria-expanded={moreOpen}
          aria-haspopup="dialog"
          onClick={() => setMoreOpen((v) => !v)}
        >
          <span className="hb-dock__icon">
            <AppIcon name="more" size={22} />
          </span>
          <span className="hb-dock__label">{t("nav.more")}</span>
        </button>
        )}
      </nav>
    </>
  );
}
