/* Akasha — Blog: markdown renderer, list, article, editor with live preview */
const { useState: bS, useEffect: bE, useRef: bR } = React;

const PKEY = "akasha_posts_v1";
function loadPosts() { try { return JSON.parse(localStorage.getItem(PKEY)) || []; } catch (e) { return []; } }
function savePosts(p) { try { localStorage.setItem(PKEY, JSON.stringify(p)); } catch (e) {} }
const BLOG_CATS = ["血流の話", "セルフケア", "妊活と身体", "気功のこと", "サロンから", "お知らせ"];
const ILLUS_NAMES = ["flow", "botanical", "profile"];

/* 管理者パスコード — 公開前にご自身の合言葉へ変更してください */
const ADMIN_CODE = "akasha";
const AUTH_KEY = "akasha_admin_ok";
function isAdmin() { try { return sessionStorage.getItem(AUTH_KEY) === "1"; } catch (e) { return false; } }

function AdminGate({ onOk }) {
  const [code, setCode] = bS("");
  const [err, setErr] = bS(false);
  function submit(e) {
    e.preventDefault();
    if (code === ADMIN_CODE) { try { sessionStorage.setItem(AUTH_KEY, "1"); } catch (x) {} onOk(); }
    else setErr(true);
  }
  return (
    <div className="page">
      <SubHero crumb="管理者ログイン" eyebrow="Admin" title="ブログの執筆は、管理者のみ。"
        lead="記事の作成・編集はサロン管理者専用です。合言葉を入力してください。" />
      <section className="section">
        <div className="wrap">
          <form className="form reveal" style={{ maxWidth: 420 }} onSubmit={submit}>
            <div className="field">
              <label>合言葉 <span className="req">必須</span></label>
              <input className="inp" type="password" value={code} autoFocus
                onChange={(e) => { setCode(e.target.value); setErr(false); }} placeholder="管理者の合言葉" />
              {err && <span className="err">合言葉が違います。もう一度お試しください。</span>}
            </div>
            <Button type="submit" variant="primary" icon="arrow-right" className="form__submit">執筆をはじめる</Button>
            <p className="muted" style={{ fontSize: 12.5, margin: 0 }}>閲覧者はブログを読むことができますが、執筆はできません。</p>
          </form>
        </div>
      </section>
    </div>
  );
}

function esc(s) { return (s || "").replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;"); }
function inlineMd(s) {
  return s
    .replace(/!\[([^\]]*)\]\(([^)\s]+)\)/g, (m, a, u) => '<img alt="' + a + '" src="' + A(u) + '">')
    .replace(/\*\*([^*]+)\*\*/g, "<strong>$1</strong>")
    .replace(/\[([^\]]+)\]\(([^)\s]+)\)/g, '<a href="$2" target="_blank" rel="noopener">$1</a>');
}
function mdToHtml(src) {
  const lines = esc(src || "").split("\n");
  const out = []; let list = null, quote = null;
  const flush = () => {
    if (list) { out.push("<ul>" + list.map((li) => `<li>${inlineMd(li)}</li>`).join("") + "</ul>"); list = null; }
    if (quote) { out.push(`<blockquote>${inlineMd(quote.join(" "))}</blockquote>`); quote = null; }
  };
  for (let raw of lines) {
    const l = raw.trim();
    if (l.startsWith("### ")) { flush(); out.push(`<h3>${inlineMd(l.slice(4))}</h3>`); }
    else if (l.startsWith("## ")) { flush(); out.push(`<h2>${inlineMd(l.slice(3))}</h2>`); }
    else if (l.startsWith("- ") || l.startsWith("・")) { if (quote) flush(); (list = list || []).push(l.replace(/^(-|・)\s*/, "")); }
    else if (l.startsWith("> ")) { if (list) flush(); (quote = quote || []).push(l.slice(2)); }
    else if (l === "") { flush(); }
    else { flush(); out.push(`<p>${inlineMd(l)}</p>`); }
  }
  flush();
  return out.join("");
}

function BlogList() {
  const ref = useReveal();
  const posts = [...loadPosts(), ...SEED_POSTS];
  return (
    <div className="page" ref={ref}>
      <SubHero crumb="ブログ" eyebrow="Journal" title="めぐりのこと、日々のこと。"
        lead="血流やセルフケアの話、サロンからのお便りを綴っています。書きたくなったら、あなたも書き手に。" />
      <section className="section">
        <div className="wrap">
          <div className="head reveal">
            <div><p className="eyebrow">Latest</p><h2 className="serif">記事一覧</h2></div>
          </div>
          {posts.length === 0 ? (
            <p className="muted">まだ記事がありません。最初の一記事を書いてみましょう。</p>
          ) : (
            <div className="blog-grid">
              {posts.map((p) => (
                <article className={`bcard reveal ${p.draft ? "bcard--draft" : ""}`} key={p.id} onClick={() => go("post/" + p.id)}>
                  <div className="bcard__media">{p.img ? <img src={A(p.img)} alt="" className="bcard__img" /> : <Illustration name={p.illus || "flow"} className="illus" />}</div>
                  <p className="bcard__cat">{p.draft ? "下書き · " : ""}{p.cat}</p>
                  <h3 className="bcard__title">{p.title || "（無題）"}</h3>
                  <p className="bcard__ex">{p.excerpt || (p.body || "").slice(0, 54)}</p>
                  <p className="bcard__date">{p.date}</p>
                </article>
              ))}
            </div>
          )}
        </div>
      </section>
    </div>
  );
}

function Article({ id }) {
  const ref = useReveal();
  const posts = [...loadPosts(), ...SEED_POSTS];
  const p = posts.find((x) => x.id === id);
  if (!p) return (
    <div className="page" ref={ref}>
      <section className="section" style={{ paddingTop: 140 }}>
        <div className="wrap center"><h2 className="serif">記事が見つかりませんでした</h2><p className="muted" style={{ marginBottom: 24 }}>削除されたか、リンクが変わった可能性があります。</p><Button variant="ghost" iconLeft="arrow-left" onClick={() => go("blog")}>ブログ一覧へ</Button></div>
      </section>
    </div>
  );
  return (
    <div className="page" ref={ref}>
      <section className="section" style={{ paddingTop: 120 }}>
        <div className="wrap">
          <div className="article reveal">
            <div className="article__head">
              <p className="eyebrow">{p.cat}</p>
              <h1 className="article__title">{p.title}</h1>
              <p className="article__meta">{p.date}{p.author ? " · " + p.author : " · Akasha"}</p>
            </div>
            {!p.img && <div className="bcard__media" style={{ aspectRatio: "16/7", marginBottom: 40 }}><Illustration name={p.illus || "flow"} className="illus" /></div>}
            <div className="article__body" dangerouslySetInnerHTML={{ __html: mdToHtml(p.body) }} />
          </div>
          <div className="center" style={{ marginTop: 56 }}><Button variant="ghost" iconLeft="arrow-left" onClick={() => go("blog")}>ブログ一覧へ戻る</Button></div>
        </div>
      </section>
    </div>
  );
}

function Editor({ id, toast }) {
  const [ok, setOk] = bS(isAdmin());
  if (!ok) return <AdminGate onOk={() => setOk(true)} />;
  return <EditorInner id={id} toast={toast} />;
}

function EditorInner({ id, toast }) {
  const existing = id ? loadPosts().find((p) => p.id === id) : null;
  const [p, setP] = bS(existing || {
    id: "p-" + Date.now(), cat: BLOG_CATS[0], title: "", excerpt: "", author: "",
    illus: "flow", date: new Date().toISOString().slice(0, 10),
    body: "ここに本文を書いていきます。\n\n## 見出し\n\n伝えたいことを、やさしい言葉で。**大切なところ**は太字にできます。\n\n- ポイントを箇条書きに\n- ひと手間のセルフケア\n\n> お客様の声も、引用として添えられます。",
  });
  const [flash, setFlash] = bS(false);
  const taRef = bR(null);
  const set = (k) => (e) => setP({ ...p, [k]: e.target.value });

  function surround(before, after) {
    const ta = taRef.current; if (!ta) return;
    const s = ta.selectionStart, e = ta.selectionEnd, val = p.body;
    const sel = val.slice(s, e) || "テキスト";
    const next = val.slice(0, s) + before + sel + after + val.slice(e);
    setP({ ...p, body: next });
    requestAnimationFrame(() => { ta.focus(); ta.selectionStart = s + before.length; ta.selectionEnd = s + before.length + sel.length; });
  }
  function prefixLine(prefix) {
    const ta = taRef.current; if (!ta) return;
    const s = ta.selectionStart, val = p.body;
    const lineStart = val.lastIndexOf("\n", s - 1) + 1;
    const next = val.slice(0, lineStart) + prefix + val.slice(lineStart);
    setP({ ...p, body: next });
    requestAnimationFrame(() => { ta.focus(); ta.selectionStart = ta.selectionEnd = s + prefix.length; });
  }
  function insertImage() {
    const url = window.prompt("画像のURLを貼り付けてください（例: https://…/photo.jpg）");
    if (!url) return;
    const ta = taRef.current, s = ta ? ta.selectionStart : p.body.length;
    const snippet = `\n\n![写真の説明](${url})\n\n`;
    setP({ ...p, body: p.body.slice(0, s) + snippet + p.body.slice(s) });
  }
  function persist(draft) {
    const rest = loadPosts().filter((x) => x.id !== p.id);
    const rec = { ...p, draft: !!draft, excerpt: p.excerpt || p.body.replace(/[#>*\-]/g, "").trim().slice(0, 60) };
    savePosts([rec, ...rest]);
    if (draft) { setFlash(true); setTimeout(() => setFlash(false), 1800); toast && toast("下書きを保存しました"); }
    else { toast && toast("記事を公開しました"); go("post/" + p.id); }
  }

  return (
    <div className="page">
      <SubHero crumb="ブログを書く" eyebrow="Write" title="めぐりのお便りを、書く。"
        lead="左に書くと、右に仕上がりが同時に映ります。見出し・太字・箇条書き・引用・画像が使えます。" />
      <section className="section" style={{ paddingTop: 40 }}>
        <div className="wrap">
          <div className="editor">
            {/* EDIT PANE */}
            <div className="editor__pane editor__pane--edit">
              <div className="editor__fields">
                <input className="inp inp--title" value={p.title} onChange={set("title")} placeholder="記事のタイトルを入力" />
                <div className="editor__meta-row">
                  <select className="inp" value={p.cat} onChange={set("cat")} style={{ flex: 1 }}>{BLOG_CATS.map((c) => <option key={c}>{c}</option>)}</select>
                  <select className="inp" value={p.illus} onChange={set("illus")} style={{ width: 140 }}>{ILLUS_NAMES.map((n) => <option key={n} value={n}>アイキャッチ: {n}</option>)}</select>
                </div>
                <input className="inp" value={p.author} onChange={set("author")} placeholder="書き手（任意・空欄ならAkasha）" />
                <input className="inp" value={p.excerpt} onChange={set("excerpt")} placeholder="一覧に出る抜粋（任意・空欄なら本文から自動）" />
              </div>
              <div className="editor__bar">
                <span className="label">本文</span>
                <button className="tbtn" title="見出し(大)" onClick={() => prefixLine("## ")}>H2</button>
                <button className="tbtn" title="見出し(小)" onClick={() => prefixLine("### ")}>H3</button>
                <button className="tbtn" title="太字" onClick={() => surround("**", "**")}><Icon name="bold" /></button>
                <button className="tbtn" title="箇条書き" onClick={() => prefixLine("- ")}><Icon name="list" /></button>
                <button className="tbtn" title="引用" onClick={() => prefixLine("> ")}><Icon name="quote" /></button>
                <button className="tbtn" title="画像を挿入" onClick={insertImage}><Icon name="image" /></button>
              </div>
              <div className="editor__area">
                <textarea className="ta" ref={taRef} value={p.body} onChange={set("body")} placeholder="本文をここに書きます…" />
              </div>
            </div>
            {/* PREVIEW PANE */}
            <div className="editor__preview">
              <div className="article">
                <div className="article__head">
                  <p className="pv-cat">{p.cat}</p>
                  <h1 className="article__title">{p.title || "（タイトル未入力）"}</h1>
                  <p className="article__meta">{p.date} · {p.author || "Akasha"}</p>
                </div>
                <div className="bcard__media" style={{ aspectRatio: "16/8", marginBottom: 26 }}><Illustration name={p.illus} className="illus" /></div>
                <div className="article__body" dangerouslySetInnerHTML={{ __html: mdToHtml(p.body) }} />
              </div>
            </div>
          </div>
          <div className="editor__actions">
            <span className="editor__hint">
              {flash ? <span className="saved-flash"><Icon name="check" />保存しました</span> : "書いた内容はこの端末に保存されます。**太字** / ## 見出し / - 箇条書き / > 引用 が使えます。"}
            </span>
            <div style={{ display: "flex", gap: 12 }}>
              <Button variant="ghost" iconLeft="save" onClick={() => persist(true)}>下書き保存</Button>
              <Button variant="primary" icon="arrow-right" onClick={() => persist(false)}>公開する</Button>
            </div>
          </div>
        </div>
      </section>
    </div>
  );
}

Object.assign(window, { BlogList, Article, Editor, mdToHtml });
