/* ============================================================
   НОВАЯ ВЕРСИЯ ГЛАВНОЙ (маршрут #new)
   Корешок на всю высоту окна + чертёжная сетка.
   Страница показывается со своей шапкой, без общей обвязки сайта,
   поэтому вся вёрстка изолирована префиксом nv- (см. styles.css).

   ПРОБНЫЙ РЕЖИМ ПРАВКИ — открывается ссылкой с ?edit=1
   (например /?edit=1#new). Тексты правятся прямо на странице,
   сохраняются в localStorage браузера и НА САЙТ НЕ ПУБЛИКУЮТСЯ.
   Кнопка «Скопировать правки» кладёт итог в буфер обмена,
   чтобы прислать разработчику и внести в код насовсем.
   Без ?edit=1 панель не показывается — ссылку /#new можно
   спокойно давать кому угодно.
   ============================================================ */

const NV_TEXT_KEY = "vm-nv-text";
const NV_LINES_KEY = "vm-nv-lines";

/* человекочитаемые подписи — нужны только для выгрузки правок */
const NV_LABELS = {
  "logo-name": "Имя в шапке",
  "logo-sub": "Подпись под именем",
  "title-1": "Заголовок, строка 1",
  "title-2": "Заголовок, строка 2",
  "lead": "Описание под заголовком",
  "eyebrow": "Надзаголовок витрины",
  "index-title": "Заголовок раздела",
  "index-link": "Ссылка «все работы»",
};

function nvLabel(id) {
  if (NV_LABELS[id]) return NV_LABELS[id];
  const m = /^w-(.+)-(t|m)$/.exec(id);
  if (m) return "Работа " + m[1] + (m[2] === "t" ? " — название" : " — подпись");
  return id;
}

/* хранилище правок текста */
function useNvText() {
  const [over, setOver] = useState(() => {
    try { return JSON.parse(localStorage.getItem(NV_TEXT_KEY) || "{}"); } catch (e) { return {}; }
  });
  const save = useCallback((id, value) => {
    setOver((prev) => {
      const next = Object.assign({}, prev);
      /* пустое значение = вернуть исходный текст (чтобы не «потерять» вёрстку) */
      if (!value) delete next[id]; else next[id] = value;
      try { localStorage.setItem(NV_TEXT_KEY, JSON.stringify(next)); } catch (e) {}
      return next;
    });
  }, []);
  const reset = useCallback(() => {
    setOver({});
    try { localStorage.removeItem(NV_TEXT_KEY); } catch (e) {}
  }, []);
  return [over, save, reset];
}

/* редактируемый фрагмент текста.
   Вне режима правки — обычный элемент, никакого оверхеда. */
function NvEd({ id, tag, className, edit, over, onSave, children }) {
  const Tag = tag || "span";
  /* правки из localStorage применяем только в режиме правки — иначе они
     перекрывали бы текст, пришедший из CMS */
  const value = edit && over[id] != null ? over[id] : children;
  if (!edit) return <Tag className={className}>{value}</Tag>;
  return (
    <Tag
      className={className}
      data-nv-ed="1"
      contentEditable
      suppressContentEditableWarning={true}
      spellCheck={false}
      title={nvLabel(id)}
      onBlur={(e) => onSave(id, e.currentTarget.innerText.replace(/\s+$/, ""))}
      onKeyDown={(e) => { if (e.key === "Escape") e.currentTarget.blur(); }}
      onClick={(e) => e.stopPropagation()}
    >
      {value}
    </Tag>
  );
}

/* значение с запоминанием в браузере — для выбора вариантов оформления */
function useNvPref(key, initial) {
  const [v, setV] = useState(() => {
    try { return localStorage.getItem(key) || initial; } catch (e) { return initial; }
  });
  useEffect(() => { try { localStorage.setItem(key, v); } catch (e) {} }, [key, v]);
  return [v, setV];
}

/* варианты, которые можно перещёлкивать на странице ?design=1 */
const NV_TYPE = [["a", "А · сейчас"], ["b", "Б · средняя"], ["c", "В · крупная"]];
const NV_WIDTH = [["1500", "1500"], ["1280", "1280"], ["1120", "1120"]];
const NV_BG = [
  ["none", "Нет"], ["v", "Вертикальные"], ["diag", "Косые"],
  ["geo", "Косые + круги"], ["geo2", "Плотная"],
];

function NewHome({ go, onOpen, theme, onToggle }) {
  const works = PHOTO;
  const n = works.length;
  const [i, setI] = useState(0);
  const [menuOpen, setMenuOpen] = useState(false);
  const [coils, setCoils] = useState(32);

  /* пробный режим доступен только по ссылке с ?edit=1 */
  const canEdit = (() => {
    try { return location.search.indexOf("edit") > -1; } catch (e) { return false; }
  })();
  const [edit, setEdit] = useState(false);
  const [panelOpen, setPanelOpen] = useState(true);
  const [msg, setMsg] = useState("");
  const [over, saveText, resetText] = useNvText();

  /* выбор оформления — открывается ссылкой ?design=1 */
  const canDesign = (() => {
    try { return location.search.indexOf("design") > -1; } catch (e) { return false; }
  })();
  const [dType, setDType] = useNvPref("vm-nv-type", "a");
  const [dWidth, setDWidth] = useNvPref("vm-nv-width", "1500");
  const [dBg, setDBg] = useNvPref("vm-nv-bg", "v");
  const designClass =
    (dType !== "a" ? " nv--type-" + dType : "") +
    (dWidth !== "1500" ? " nv--w-" + dWidth : "") +
    (dBg !== "v" ? " nv--bg-" + dBg : "");
  const [lines, setLines] = useState(() => {
    try { return localStorage.getItem(NV_LINES_KEY) !== "off"; } catch (e) { return true; }
  });
  useEffect(() => {
    try { localStorage.setItem(NV_LINES_KEY, lines ? "on" : "off"); } catch (e) {}
  }, [lines]);

  /* автосмена кадра — на время правки останавливаем, чтобы текст не «уезжал» */
  useEffect(() => {
    if (edit) return;
    const t = setInterval(() => setI((v) => (v + 1) % n), 6000);
    return () => clearInterval(t);
  }, [n, edit]);

  /* стрелки листают, Esc закрывает меню.
     Внутри редактируемого текста стрелки должны двигать курсор, а не витрину. */
  useEffect(() => {
    const onKey = (e) => {
      if (e.target && e.target.isContentEditable) return;
      if (e.key === "ArrowLeft") setI((v) => (v - 1 + n) % n);
      else if (e.key === "ArrowRight") setI((v) => (v + 1) % n);
      else if (e.key === "Escape") setMenuOpen(false);
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [n]);

  /* витков в корешке — столько, сколько влезает по высоте окна */
  useEffect(() => {
    const fill = () => setCoils(Math.ceil(window.innerHeight / 26) + 2);
    fill();
    window.addEventListener("resize", fill);
    return () => window.removeEventListener("resize", fill);
  }, []);

  /* открытое меню не даёт странице прокручиваться */
  useEffect(() => {
    document.body.style.overflow = menuOpen ? "hidden" : "";
    return () => { document.body.style.overflow = ""; };
  }, [menuOpen]);

  const cur = works[i];
  const pad = (v) => String(v).padStart(2, "0");
  const nav = NAVITEMS.filter((it) => it.key !== "new");
  const openPhoto = (idx) => { if (edit) return; onOpen ? onOpen("photo", idx) : go("photo"); };

  const flash = (t) => { setMsg(t); setTimeout(() => setMsg(""), 2600); };
  const copyEdits = () => {
    const keys = Object.keys(over);
    if (!keys.length) { flash("Правок пока нет"); return; }
    const text = "Правки текста — главная (новая версия)\n\n" +
      keys.map((k) => nvLabel(k) + ":\n" + over[k]).join("\n\n");
    if (window.console) console.log(text);
    try {
      navigator.clipboard.writeText(text)
        .then(() => flash("Скопировано"), () => flash("Текст выведен в консоль"));
    } catch (e) { flash("Текст выведен в консоль"); }
  };

  /* сокращение, чтобы не повторять общие пропсы у каждого текста */
  const ed = { edit: edit, over: over, onSave: saveText };

  return (
    <div className={"nv" + (lines ? "" : " nv--nolines") + (edit ? " nv--edit" : "") + designClass}>
      <div className="nv-draft" aria-hidden="true" />
      <div className="nv-spine" aria-hidden="true">
        <div className="nv-coil">
          {Array.from({ length: coils }).map((_, k) => <i key={k} />)}
        </div>
      </div>

      <div className="nv-shell">
        <header className="nv-header">
          <div className="nv-wrap nv-header__row">
            <div className="nv-logo">
              <span className="nv-logo__mark" />
              <span className="nv-logo__name">
                <NvEd tag="b" id="logo-name" {...ed}>{SITE.logoName}</NvEd>
                <NvEd id="logo-sub" {...ed}>{SITE.logoSub}</NvEd>
              </span>
            </div>

            <nav className="nv-nav">
              {nav.map((it, k) => (
                <a key={it.key} href={"#" + it.key}
                  className={it.key === "home" ? "is-on" : ""}
                  onClick={(e) => { e.preventDefault(); go(it.key); }}>
                  <span className="nv-n">{pad(k + 1)}</span>{it.label}
                </a>
              ))}
            </nav>

            <div className="nv-header__right">
              <button className="nv-tt" onClick={onToggle}>
                <span>{theme === "dark" ? "Тёмная" : "Светлая"}</span><b />
              </button>
              <button className="nv-burger" aria-label="Меню" aria-expanded={menuOpen}
                onClick={() => setMenuOpen((o) => !o)}><i /></button>
            </div>
          </div>
        </header>

        <div className={"nv-sheet" + (menuOpen ? " is-open" : "")}>
          <nav>
            {nav.map((it, k) => (
              <a key={it.key} href={"#" + it.key}
                onClick={(e) => { e.preventDefault(); setMenuOpen(false); go(it.key); }}>
                <span className="nv-n">{pad(k + 1)}</span>{it.label}
              </a>
            ))}
          </nav>
          <div className="nv-sheet__foot">Архив · 2022—2025</div>
        </div>

        <main className="nv-wrap">
          <div className="nv-mast">
            <h1>
              <NvEd tag="em" id="title-1" {...ed}>{SITE.homeTitle1}</NvEd><br />
              <NvEd id="title-2" {...ed}>{SITE.homeTitle2}</NvEd>
            </h1>
            <NvEd tag="p" id="lead" {...ed}>
              {SITE.homeLead}
            </NvEd>
          </div>

          <div className="nv-stage">
            <div className="nv-frame" onClick={() => openPhoto(i)} role="button" tabIndex={0}
              aria-label={"Открыть: " + cur.title}
              onKeyDown={(e) => { if (e.key === "Enter") openPhoto(i); }}>
              <div className="nv-frame__dim" />
              {works.map((w, k) => (
                <div className={"nv-slide" + (k === i ? " is-on" : "")} key={w.id}>
                  <img src={w.src} alt={w.title} loading={k === 0 ? "eager" : "lazy"} />
                </div>
              ))}
            </div>

            <div className="nv-meta">
              <span className="nv-meta__eyebrow">
                <NvEd id="eyebrow" {...ed}>{SITE.eyebrow}</NvEd> · {pad(i + 1)}
              </span>
              <div className="nv-meta__now" key={cur.id}>
                <h2><NvEd id={"w-" + cur.id + "-t"} {...ed}>{cur.title}</NvEd></h2>
                <NvEd className="nv-mm" id={"w-" + cur.id + "-m"} {...ed}>{cur.meta}</NvEd>
              </div>
              <hr className="nv-rule" />
              <div className="nv-dots">
                {works.map((w, k) => (
                  <span key={w.id} className={"nv-d" + (k === i ? " is-on" : "")}
                    onClick={() => setI(k)} role="button" tabIndex={0}
                    aria-label={"Кадр " + pad(k + 1)}
                    onKeyDown={(e) => { if (e.key === "Enter") setI(k); }} />
                ))}
                <span className="nv-count">{pad(i + 1)} — {pad(n)}</span>
              </div>
              <div className="nv-ctrl">
                <button onClick={() => setI((v) => (v - 1 + n) % n)} aria-label="Назад"><Icon.left /></button>
                <button onClick={() => setI((v) => (v + 1) % n)} aria-label="Вперёд"><Icon.right /></button>
              </div>
            </div>
          </div>

          <div className="nv-index">
            <div className="nv-sechead">
              <h2><NvEd id="index-title" {...ed}>{SITE.indexTitle}</NvEd></h2>
              <a href="#photo" onClick={(e) => { e.preventDefault(); if (!edit) go("photo"); }}>
                <NvEd id="index-link" {...ed}>{SITE.indexLink}</NvEd>
              </a>
            </div>
            <div className="nv-grid">
              {works.map((w, k) => (
                <figure key={w.id} onClick={() => openPhoto(k)} role="button" tabIndex={0}
                  onKeyDown={(e) => { if (e.key === "Enter") openPhoto(k); }}>
                  <img src={w.src} alt={w.title} loading="lazy" />
                  <figcaption className="nv-cap">
                    <NvEd className="nv-t" id={"w-" + w.id + "-t"} {...ed}>{w.title}</NvEd>
                    <NvEd className="nv-m" id={"w-" + w.id + "-m"} {...ed}>{w.meta}</NvEd>
                  </figcaption>
                </figure>
              ))}
            </div>
          </div>
        </main>
      </div>

      {canDesign && (
        <div className="nv-design">
          {panelOpen && (
            <div className="nv-design__body">
              <div className="nv-design__group">
                <span className="nv-design__label">Шрифт</span>
                <div className="nv-design__row">
                  {NV_TYPE.map(([v, t]) => (
                    <button key={v} className={dType === v ? "is-on" : ""} onClick={() => setDType(v)}>{t}</button>
                  ))}
                </div>
              </div>
              <div className="nv-design__group">
                <span className="nv-design__label">Ширина колонки</span>
                <div className="nv-design__row">
                  {NV_WIDTH.map(([v, t]) => (
                    <button key={v} className={dWidth === v ? "is-on" : ""} onClick={() => setDWidth(v)}>{t}</button>
                  ))}
                </div>
              </div>
              <div className="nv-design__group">
                <span className="nv-design__label">Линии на фоне</span>
                <div className="nv-design__row">
                  {NV_BG.map(([v, t]) => (
                    <button key={v} className={dBg === v ? "is-on" : ""} onClick={() => setDBg(v)}>{t}</button>
                  ))}
                </div>
              </div>
              <div className="nv-design__code">
                Понравилось — назовите сочетание:<br />
                <b>Шрифт {dType.toUpperCase()} · Ширина {dWidth} · Фон «{(NV_BG.find((x) => x[0] === dBg) || [])[1]}»</b>
              </div>
            </div>
          )}
          <button className="nv-design__toggle" onClick={() => setPanelOpen((o) => !o)}>
            {panelOpen ? "Свернуть" : "Варианты"}
          </button>
        </div>
      )}

      {canEdit && (
        <div className="nv-panel">
          {panelOpen && (
            <div className="nv-panel__body">
              <label className="nv-panel__row">
                <input type="checkbox" checked={edit} onChange={(e) => setEdit(e.target.checked)} />
                <span>Правка текста</span>
              </label>
              <label className="nv-panel__row">
                <input type="checkbox" checked={lines} onChange={(e) => setLines(e.target.checked)} />
                <span>Линии на фоне</span>
              </label>
              <div className="nv-panel__btns">
                <button onClick={copyEdits}>Скопировать правки</button>
                <button onClick={resetText}>Сбросить текст</button>
              </div>
              {msg && <div className="nv-panel__msg">{msg}</div>}
              <p className="nv-panel__note">
                Включите «Правку текста» и щёлкните по любой надписи. Правки видны
                только в этом браузере и на сайт не публикуются — чтобы внести их
                насовсем, нажмите «Скопировать правки» и пришлите текст.
              </p>
            </div>
          )}
          <button className="nv-panel__toggle" onClick={() => setPanelOpen((o) => !o)}>
            {panelOpen ? "Свернуть" : "Пробный режим"}
          </button>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { NewHome, NvEd });
