/* HaloScape Feedback Hub — main app (HaloScape editorial) */
/* global React, ReactDOM, TopNav, Hero, SubmitForm, PostCard, ListHead, PostModal, ModerationPage, BugReportsPage, SurveyPage, EmailCaptureModal, BugReportModal, AdminLoginModal, TweaksPanel, Footer, SEED_POSTS, SEED_BOARDS, BOARD_VISUALS, DEFAULT_TINTS, db, auth */

const { useState, useMemo, useEffect, useRef } = React;

const TWEAKS_KEY      = 'haloscape-feedback-tweaks-v4';
const SURVEY_KEY      = 'haloscape-survey-v2';
const SITE_CONFIG_KEY = 'haloscape-config-v1';

const DEFAULT_BOARD_TITLES = {
  features: 'What would make us better?',
  feedback:  "What's on your mind?",
};

const DEFAULT_BOARD_PLACEHOLDERS = {
  feedback: {
    title:   'e.g. My Halo Score surprised me today.',
    details: 'What happened? What did you expect to see?',
  },
  features: {
    title:   'e.g. New wearable integration.',
    details: 'Which part of your health tracking journey would this improve?',
  },
};

const loadConfig = () => {
  try {
    const raw = localStorage.getItem(SITE_CONFIG_KEY);
    if (raw) return JSON.parse(raw);
  } catch {}
  return { boardTitles: {} };
};

const DEFAULT_SURVEY_TOPICS = [
  { id: 'st1', title: 'Overall Experience',    description: 'How would you rate HaloScape overall?' },
  { id: 'st2', title: 'Onboarding Flow',        description: 'How was your first-time setup experience?' },
  { id: 'st3', title: 'Features & Insights',   description: 'Are the health insights meeting your needs?' },
];

const loadTweaks = () => {
  try {
    const raw = localStorage.getItem(TWEAKS_KEY);
    if (raw) return JSON.parse(raw);
  } catch {}
  return { mode: 'light', accent: 'ink', layout: 'grid', showTweaks: false };
};
const loadSurvey = () => {
  try {
    const raw = localStorage.getItem(SURVEY_KEY);
    if (raw) return JSON.parse(raw);
  } catch {}
  return { topics: DEFAULT_SURVEY_TOPICS, responses: {}, completed: [] };
};

const BOARD_COLORS = ['#6810DD','#E43D41','#0D4638','#E69BED','#01A0A7','#FFA785'];
const slugify = (s) => s.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') || ('board-' + Date.now());

const BOARD_COLLECTION = { features: 'halofeature', feedback: 'halofeedback', bugs: 'halobug' };
const collectionFor = (boardId) => BOARD_COLLECTION[boardId] || 'halofeature';

const BOARD_ORDER = ['feedback', 'features', 'bugs'];
const sortBoards = (arr) => [...arr].sort((a, b) => {
  const ai = BOARD_ORDER.indexOf(a.id);
  const bi = BOARD_ORDER.indexOf(b.id);
  return (ai === -1 ? 999 : ai) - (bi === -1 ? 999 : bi);
});

function boardTintFor(board, index) {
  const v = BOARD_VISUALS[board.id];
  if (v) return v.tint;
  return DEFAULT_TINTS[index % DEFAULT_TINTS.length];
}

// ── Firestore helpers ─────────────────────────────────────────
function postFromDoc(doc) {
  return { id: doc.id, ...doc.data() };
}

function boardFromDoc(doc) {
  return { id: doc.id, ...doc.data() };
}


function App() {
  const [posts,      setPosts]      = useState([]);
  const [boards,     setBoards]     = useState(SEED_BOARDS);
  const [votes,      setVotes]      = useState({});
  const [currentBoard, setCurrentBoard] = useState('feedback');
  const [openPostId, setOpenPostId] = useState(null);
  const [page,       setPageState]  = useState('hub');
  const [loading,    setLoading]    = useState(true);

  const [tweaks,     setTweaks]     = useState(loadTweaks);
  const [surveyData, setSurveyData] = useState(loadSurvey);
  const [siteConfig, setSiteConfig] = useState(loadConfig);
  const [sort,       setSort]       = useState('trending');
  const [query,      setQuery]      = useState('');
  const [showEmailModal,   setShowEmailModal]   = useState(false);
  const [emailModalIsBug,  setEmailModalIsBug]  = useState(false);
  const [showBugModal,     setShowBugModal]     = useState(false);
  const [showAdminModal,   setShowAdminModal]   = useState(false);
  const [adminMode,        setAdminModeState]   = useState(false);

  const submitRef          = useRef(null);
  const listRef            = useRef(null);
  const lastSubmittedIdRef = useRef(null);

  // ── Open admin modal if URL path is /admin-login ─────────────
  useEffect(() => {
    if (window.location.pathname === '/admin-login') {
      setShowAdminModal(true);
    }
  }, []);

  // ── Firebase Auth listener ────────────────────────────────────
  useEffect(() => {
    const unsub = auth.onAuthStateChanged(user => {
      setAdminModeState(!!user);
      if (!user && (page === 'moderation' || page === 'bugs')) setPageState('hub');
    });
    return unsub;
  }, []);


  // ── Firestore real-time listeners ────────────────────────────
  useEffect(() => {
    let unsubs = [() => {}, () => {}, () => {}, () => {}];
    const postsMap = { halofeature: [], halofeedback: [], halobug: [] };

    const mergeAndSet = () => {
      setPosts([...postsMap.halofeature, ...postsMap.halofeedback, ...postsMap.halobug]);
    };

    Promise.resolve()
      .then(() => {
        ['halofeature', 'halofeedback', 'halobug'].forEach((col, i) => {
          unsubs[i] = db.collection(col)
            .orderBy('createdAt', 'desc')
            .onSnapshot(
              snap => { postsMap[col] = snap.docs.map(postFromDoc); mergeAndSet(); setLoading(false); },
              err  => { console.error(col + ' error:', err); setLoading(false); }
            );
        });

        unsubs[3] = db.collection('boards')
          .onSnapshot(
            snap => { const rows = snap.docs.map(boardFromDoc); if (rows.length > 0) setBoards(sortBoards(rows)); },
            err  => { console.error('boards error:', err); }
          );
      })
      .catch(err => { console.error('Firebase init error:', err); setLoading(false); });

    return () => unsubs.forEach(u => u());
  }, []);

  // ── Votes stay in localStorage (per-device, anonymous) ───────
  useEffect(() => {
    try {
      const raw = localStorage.getItem('haloscape-votes-v1');
      if (raw) setVotes(JSON.parse(raw));
    } catch {}
  }, []);
  const persistVotes = (v) => {
    setVotes(v);
    localStorage.setItem('haloscape-votes-v1', JSON.stringify(v));
  };

  // ── Tweaks / survey / config stay in localStorage ────────────
  useEffect(() => { localStorage.setItem(TWEAKS_KEY,      JSON.stringify(tweaks)); },     [tweaks]);
  useEffect(() => { localStorage.setItem(SURVEY_KEY,      JSON.stringify(surveyData)); }, [surveyData]);
  useEffect(() => { localStorage.setItem(SITE_CONFIG_KEY, JSON.stringify(siteConfig)); }, [siteConfig]);

  useEffect(() => {
    const root = document.documentElement;
    root.setAttribute('data-mode',   tweaks.mode);
    root.setAttribute('data-accent', tweaks.accent);
  }, [tweaks.mode, tweaks.accent]);

  useEffect(() => {
    const handler = (e) => {
      if (!e?.data?.type) return;
      if (e.data.type === '__activate_edit_mode')   setTweaks(t => ({ ...t, showTweaks: true }));
      if (e.data.type === '__deactivate_edit_mode') setTweaks(t => ({ ...t, showTweaks: false }));
    };
    window.addEventListener('message', handler);
    window.parent.postMessage({ type: '__edit_mode_available' }, '*');
    return () => window.removeEventListener('message', handler);
  }, []);

  const publicBoards = adminMode ? boards : boards.filter(b => b.id !== 'bugs');

  const byBoard = useMemo(() => {
    const m = {};
    boards.forEach(b => m[b.id] = []);
    posts.forEach(p => { if (m[p.boardId]) m[p.boardId].push(p); });
    return m;
  }, [posts, boards]);

  const currentBoardObj = (adminMode ? boards : publicBoards).find(b => b.id === currentBoard)
    || (adminMode ? boards[0] : publicBoards[0]) || SEED_BOARDS[0];
  const currentBoardIndex = boards.findIndex(b => b.id === currentBoardObj.id);
  const currentTint = boardTintFor(currentBoardObj, currentBoardIndex);

  const publicPosts = useMemo(() => {
    let rows = (byBoard[currentBoardObj.id] || []).filter(p => p.moderation === 'approved');
    if (query.trim()) {
      const q = query.toLowerCase();
      rows = rows.filter(p => p.title.toLowerCase().includes(q));
    }
    rows = [...rows];
    if (sort === 'newest')   rows.sort((a,b) => new Date(b.createdAt) - new Date(a.createdAt));
    else if (sort === 'top') rows.sort((a,b) => b.votes - a.votes);
    else {
      const now = Date.now();
      rows.sort((a,b) => {
        const sa = a.votes / (1 + (now - new Date(a.createdAt))/(1000*60*60*24*14));
        const sb = b.votes / (1 + (now - new Date(b.createdAt))/(1000*60*60*24*14));
        return sb - sa;
      });
    }
    return rows;
  }, [byBoard, currentBoardObj.id, query, sort]);

  const pendingCount = useMemo(() =>
    posts.filter(p => p.moderation === 'pending' || !p.moderation).length
  , [posts]);

  // ── Navigation ─────────────────────────────────────────────
  const pickBoardAndScroll = (id) => {
    setCurrentBoard(id);
    setPageState('hub');
    setOpenPostId(null);
    setTimeout(() => {
      if (submitRef.current) {
        const navEl = document.querySelector('.nav');
        const navH = navEl ? navEl.offsetHeight : 72;
        const top = submitRef.current.getBoundingClientRect().top + window.scrollY - navH - 8;
        window.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
      }
    }, 200);
  };

  const setPage = (p) => { setPageState(p); setOpenPostId(null); };

  const scrollToSubmit = () => {
    if (submitRef.current) {
      const navEl = document.querySelector('.nav');
      const navH = navEl ? navEl.offsetHeight : 72;
      const top = submitRef.current.getBoundingClientRect().top + window.scrollY - navH - 8;
      window.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
    }
  };

  // ── Vote ────────────────────────────────────────────────────
  const toggleVote = (id) => {
    const isVoted = !!votes[id];
    const delta   = isVoted ? -1 : 1;
    const newVotes = { ...votes };
    if (isVoted) delete newVotes[id]; else newVotes[id] = true;
    persistVotes(newVotes);
    const post = posts.find(p => p.id === id);
    db.collection(collectionFor(post?.boardId)).doc(id).update({
      votes: firebase.firestore.FieldValue.increment(delta),
    });
  };

  // ── Posts ───────────────────────────────────────────────────
  const addPost = ({ title, details }) => {
    const id  = 'p' + Date.now();
    lastSubmittedIdRef.current = id;
    db.collection(collectionFor(currentBoard)).doc(id).set({
      boardId: currentBoard, title, details, votes: 1,
      moderation: 'pending', status: null,
      createdAt: new Date().toISOString(), comments: [],
    });
    const newVotes = { ...votes, [id]: true };
    persistVotes(newVotes);
    setEmailModalIsBug(false);
    setShowEmailModal(true);
  };

  const addBugPost = ({ title, details, files }) => {
    const id = 'b' + Date.now();
    lastSubmittedIdRef.current = id;
    db.collection('halobug').doc(id).set({
      boardId: 'bugs', title, details,
      attachments: files || [],
      votes: 1, moderation: 'approved', status: null,
      createdAt: new Date().toISOString(), comments: [],
    });
    const newVotes = { ...votes, [id]: true };
    persistVotes(newVotes);
    setEmailModalIsBug(true);
    setShowEmailModal(true);
  };

  const setModeration = (id, value) => {
    const post = posts.find(p => p.id === id);
    db.collection(collectionFor(post?.boardId)).doc(id).update({ moderation: value });
  };

  const setStatus = (id, value) => {
    const post = posts.find(p => p.id === id);
    db.collection(collectionFor(post?.boardId)).doc(id).update({ status: value === 'open' ? null : value });
  };

  const addComment = (postId, body) => {
    const post = posts.find(p => p.id === postId);
    if (!post) return;
    const comment = {
      id: 'c' + Date.now(), author: 'Anonymous',
      body: body.trim(), createdAt: new Date().toISOString(),
    };
    db.collection(collectionFor(post.boardId)).doc(postId).update({
      comments: firebase.firestore.FieldValue.arrayUnion(comment),
    });
  };

  // ── Boards ──────────────────────────────────────────────────
  const addBoard = (name) => {
    let id = slugify(name);
    let i = 1; while (boards.find(b => b.id === id)) { id = slugify(name) + '-' + (++i); }
    const color = BOARD_COLORS[boards.length % BOARD_COLORS.length];
    db.collection('boards').doc(id).set({ name, color });
    setCurrentBoard(id);
  };

  const removeBoard = (id) => {
    const remaining = boards.filter(b => b.id !== id);
    if (remaining.length === 0) return;
    db.collection('boards').doc(id).delete();
    posts.filter(p => p.boardId === id).forEach(p => db.collection(collectionFor(id)).doc(p.id).delete());
    if (currentBoard === id) setCurrentBoard(remaining[0].id);
  };

  // ── Survey ──────────────────────────────────────────────────
  const submitSurvey = (topicId, { score, text, date }) => setSurveyData(s => ({
    ...s,
    responses: {
      ...s.responses,
      [topicId]: [...(s.responses[topicId] || []), { score, text, date }],
    },
    completed: (s.completed || []).includes(topicId)
      ? s.completed
      : [...(s.completed || []), topicId],
  }));

  const addSurveyTopic = ({ title, description }) => setSurveyData(s => ({
    ...s,
    topics: [...(s.topics || []), { id: 'st' + Date.now(), title, description }],
  }));

  const removeSurveyTopic = (id) => setSurveyData(s => ({
    ...s,
    topics: (s.topics || []).filter(t => t.id !== id),
  }));

  const setAdminMode = (v) => {
    if (!v) auth.signOut();
  };

  const setBoardText = (key, value) => setSiteConfig(c => ({
    ...c,
    boardTitles: { ...c.boardTitles, [key]: value },
  }));

  const getBoardHeroTitle = (boardId) => {
    if (siteConfig.boardTitles && siteConfig.boardTitles[boardId]) return siteConfig.boardTitles[boardId];
    return DEFAULT_BOARD_TITLES[boardId] || 'What should we do next?';
  };

  const getBoardFormTitle = (boardId) => {
    if (siteConfig.boardTitles && siteConfig.boardTitles['form_' + boardId]) return siteConfig.boardTitles['form_' + boardId];
    return undefined;
  };

  const openPostObj   = openPostId ? posts.find(p => p.id === openPostId) : null;
  const openPostBoard = openPostObj ? boards.find(b => b.id === openPostObj.boardId) : null;
  const openPostTint  = openPostObj ? boardTintFor(openPostBoard, boards.findIndex(b => b.id === (openPostBoard && openPostBoard.id))) : 'teal';

  if (loading) {
    return (
      <div style={{display:'flex',alignItems:'center',justifyContent:'center',minHeight:'100vh',flexDirection:'column',gap:'16px'}}>
        <div style={{width:'40px',height:'40px',border:'3px solid var(--hairline)',borderTopColor:'var(--fg-1)',borderRadius:'50%',animation:'spin 0.8s linear infinite'}}/>
        <style>{`@keyframes spin{to{transform:rotate(360deg)}}`}</style>
        <span style={{fontSize:'14px',color:'var(--fg-3)'}}>Loading…</span>
      </div>
    );
  }

  return (
    <div className="app" data-layout={tweaks.layout}>
      <TopNav
        boards={publicBoards}
        currentBoardId={currentBoardObj.id}
        onPick={pickBoardAndScroll}
        adminMode={adminMode}
        setAdminMode={setAdminMode}
        page={page}
        setPage={setPage}
        pendingCount={pendingCount}
        onAddBoard={addBoard}
        onRemoveBoard={removeBoard}
      />

      <main className="main">
        {page === 'hub' && (
          <div data-screen-label="01 Feedback Hub">
            <Hero
              onPrimary={() => { setPage('hub'); setTimeout(scrollToSubmit, 80); }}
              onBugReport={() => setShowBugModal(true)}
              heroTitle={getBoardHeroTitle(currentBoardObj.id)}
              adminMode={adminMode}
              onEditTitle={(value) => setBoardText(currentBoardObj.id, value)}
            />

            <SubmitForm
              boardName={currentBoardObj.name}
              boardTint={currentTint}
              boardColor={currentBoardObj.color}
              onSubmit={addPost}
              innerRef={submitRef}
              formTitle={getBoardFormTitle(currentBoardObj.id)}
              adminMode={adminMode}
              onEditFormTitle={(value) => setBoardText('form_' + currentBoardObj.id, value)}
              titlePlaceholder={siteConfig.boardTitles?.['ph_title_' + currentBoardObj.id] || DEFAULT_BOARD_PLACEHOLDERS[currentBoardObj.id]?.title}
              detailsPlaceholder={siteConfig.boardTitles?.['ph_details_' + currentBoardObj.id] || DEFAULT_BOARD_PLACEHOLDERS[currentBoardObj.id]?.details}
              onEditTitlePlaceholder={(v) => setBoardText('ph_title_' + currentBoardObj.id, v)}
              onEditDetailsPlaceholder={(v) => setBoardText('ph_details_' + currentBoardObj.id, v)}
            />

            <section className="list-section" ref={listRef}>
              <ListHead
                sort={sort} setSort={setSort}
                query={query} setQuery={setQuery}
                count={publicPosts.length}
                boardName={currentBoardObj.name}
              />

              {publicPosts.length === 0 ? (
                <div className="empty-card">
                  <div className="empty-big">No posts yet in {currentBoardObj.name}</div>
                  <p>Be the first to share an idea — your post appears here after a brief review.</p>
                  <button className="btn btn-primary btn-pill" onClick={scrollToSubmit}>Post feedback</button>
                </div>
              ) : (
                <div className="post-grid" data-layout={tweaks.layout}>
                  {publicPosts.map(p => (
                    <PostCard
                      key={p.id} post={p}
                      voted={!!votes[p.id]}
                      onVote={toggleVote}
                      onOpen={setOpenPostId}
                      boardLabel={currentBoardObj.name}
                      boardTint={currentTint}
                      adminMode={adminMode}
                    />
                  ))}
                </div>
              )}
            </section>
          </div>
        )}

        {page === 'survey' && (
          <div data-screen-label="04 Survey">
            <SurveyPage
              adminMode={adminMode}
              surveyData={surveyData}
              onSubmit={submitSurvey}
              onAddTopic={addSurveyTopic}
              onRemoveTopic={removeSurveyTopic}
            />
          </div>
        )}

        {page === 'moderation' && (
          <div data-screen-label="02 Moderation">
            <ModerationPage
              posts={posts.filter(p => p.boardId !== 'bugs')}
              boards={publicBoards}
              onSet={setModeration}
              onSetStatus={setStatus}
              onOpen={setOpenPostId}
              adminMode={adminMode}
            />
          </div>
        )}

        {page === 'bugs' && (
          <div data-screen-label="03 Bug Reports">
            <BugReportsPage
              posts={posts}
              onSetStatus={setStatus}
              onOpen={setOpenPostId}
              adminMode={adminMode}
            />
          </div>
        )}
      </main>

      {openPostObj && (
        <PostModal
          post={openPostObj}
          voted={!!votes[openPostObj.id]}
          onVote={toggleVote}
          onClose={() => setOpenPostId(null)}
          boardLabel={openPostBoard?.name || '—'}
          boardTint={openPostTint}
          onComment={addComment}
          adminMode={adminMode}
        />
      )}

      {showBugModal && (
        <BugReportModal
          onClose={() => setShowBugModal(false)}
          onSubmit={addBugPost}
        />
      )}

      {showEmailModal && (
        <EmailCaptureModal
          isBugReport={emailModalIsBug}
          onClose={() => setShowEmailModal(false)}
          onSubmit={(email) => {
            const id = lastSubmittedIdRef.current;
            if (id) {
              const post = posts.find(p => p.id === id);
              db.collection(collectionFor(post?.boardId)).doc(id).update({ email });
              lastSubmittedIdRef.current = null;
            }
            window.subscribeToMailchimp(email).catch(() => {});
            setShowEmailModal(false);
          }}
        />
      )}

      {showAdminModal && (
        <AdminLoginModal
          onClose={() => setShowAdminModal(false)}
          onSuccess={() => setShowAdminModal(false)}
        />
      )}

      <TweaksPanel tweaks={tweaks} setTweaks={setTweaks} visible={tweaks.showTweaks} />
      <Footer/>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<App/>);
