/* global React, ReactDOM, Banner, FilterBar, IndexView, SundayDetail, ScriptureModal, ResourcesView, ResourceSetView, ChurchYearView, BlankPage */
const { useState, useEffect, useMemo, useCallback } = React;

const SERIES_LABELS = {
  'LSB-3Y-A': 'Three-Year Series A',
  'LSB-3Y-B': 'Three-Year Series B',
  'LSB-3Y-C': 'Three-Year Series C',
  'LSB-1Y': 'One-Year Historic',
};
const SERIES_SLUG = {
  'LSB-3Y-A': 'three-year-a',
  'LSB-3Y-B': 'three-year-b',
  'LSB-3Y-C': 'three-year-c',
  'LSB-1Y': 'one-year',
};
const DEFAULT_SERIES = 'LSB-3Y-A';
const SERIES_FROM_SLUG = Object.fromEntries(
  Object.entries(SERIES_SLUG).map(([k, v]) => [v, k])
);
const BROWSER_TITLE_BASE = 'LSB Lectionary';

// Slug helpers
function toSlug(name) {
  return name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-+|-+$/g, '');
}

// URL helpers
function buildPath({ view, series, sunday, resourceSetId }) {
  if (view === 'church-year' || !view) return '/';
  if (view === 'about') return '/about';
  if (view === 'copyright') return '/copyright';
  if (view === 'resources') {
    if (resourceSetId) return `/resources/${resourceSetId}`;
    return '/resources';
  }
  if (view === 'lectionary') {
    const seriesSlug = SERIES_SLUG[series] || 'three-year-a';
    if (sunday != null) {
      const entries = (window.LECTIONARY_DATA && window.LECTIONARY_DATA[series]) || [];
      const entry = entries[sunday];
      if (entry) return `/lectionary/${seriesSlug}/${toSlug(entry.Sunday)}`;
    }
    return `/lectionary/${seriesSlug}/`;
  }
  return '/';
}

function parsePath(pathname) {
  const parts = (pathname || '/').replace(/^\//, '').split('/').filter(Boolean);
  if (parts.length === 0) return { view: 'church-year', series: DEFAULT_SERIES, sunday: null, resourceSetId: null };
  const first = parts[0];
  if (first === 'about') return { view: 'about', series: DEFAULT_SERIES, sunday: null, resourceSetId: null };
  if (first === 'copyright') return { view: 'copyright', series: DEFAULT_SERIES, sunday: null, resourceSetId: null };
  if (first === 'resources') {
    const resourceSetId = parts[1] || null;
    return { view: 'resources', series: DEFAULT_SERIES, sunday: null, resourceSetId };
  }
  if (first === 'lectionary') {
    const series = SERIES_FROM_SLUG[parts[1]] || DEFAULT_SERIES;
    if (parts[2]) {
      const entries = (window.LECTIONARY_DATA && window.LECTIONARY_DATA[series]) || [];
      const idx = entries.findIndex(e => toSlug(e.Sunday) === parts[2]);
      return { view: 'lectionary', series, sunday: idx >= 0 ? idx : null, resourceSetId: null };
    }
    return { view: 'lectionary', series, sunday: null, resourceSetId: null };
  }
  return { view: 'church-year', series: DEFAULT_SERIES, sunday: null, resourceSetId: null };
}

function seriesTitleCode(series) {
  const threeYear = /^LSB-3Y-([A-C])$/.exec(series || '');
  if (threeYear) return `3Y${threeYear[1]}`;
  if (series === 'LSB-1Y') return '1Y';
  return series || '';
}

function buildDocumentTitle({ view, series, selectedEntry, resourceSetId }) {
  let subtitle = '';

  if (view === 'lectionary') {
    const code = seriesTitleCode(series);
    subtitle = selectedEntry ? `${selectedEntry.Sunday} (${code})` : `Lectionary (${code})`;
  } else if (view === 'resources') {
    const resourceSet = resourceSetId
      ? (window.RESOURCE_SETS || []).find((set) => set.id === resourceSetId)
      : null;
    subtitle = resourceSet?.title || 'Resources';
  } else if (view === 'about') {
    subtitle = 'About';
  } else if (view === 'copyright') {
    subtitle = 'Copyright Notices';
  }

  return subtitle ? `${BROWSER_TITLE_BASE} - ${subtitle}` : BROWSER_TITLE_BASE;
}

// Default Church Year = the liturgical year currently in progress
// (today's calendar year, or next year if we're past Advent 1).
function defaultCYYear() {
  const today = new Date();
  const cy = today.getFullYear();
  const next = window.LSB_buildChurchYear(cy + 1);
  const advent1Next = next.items[0]?.date;
  return advent1Next && today >= advent1Next ? cy + 1 : cy;
}

// Returns { seriesId, idx } for the first upcoming Sunday that has lectionary data.
function findNextSunday() {
  const today = new Date();
  today.setHours(0, 0, 0, 0);
  try {
    const churchYear = window.LSB_buildChurchYear(defaultCYYear());
    const seriesId = `LSB-3Y-${churchYear.seriesLetter}`;
    const entries = window.LECTIONARY_DATA[seriesId] || [];
    const byKey = {};
    entries.forEach((e, idx) => { byKey[e.Sunday] = idx; });
    for (const item of churchYear.items) {
      if (item.date < today) continue;
      const idx = byKey[item.sundayKey];
      if (idx !== undefined) return { seriesId, idx };
    }
  } catch {}
  return null;
}

function App() {
  const initial = parsePath(window.location.pathname);
  const [view, setView] = useState(initial.view);
  const [series, setSeries] = useState(initial.series);
  const [selectedIdx, setSelectedIdx] = useState(initial.sunday);
  const [resourceSetId, setResourceSetId] = useState(initial.resourceSetId ?? null);
  const [query, setQuery] = useState('');
  const [activeSeasons, setActiveSeasons] = useState([]);
  const [scriptureModal, setScriptureModal] = useState(null);

  // Church Year page state
  const [cySeriesForm, setCYSeriesForm] = useState('3Y');
  const [cyYear, setCYYear] = useState(() => {
    try { return window.LSB_buildChurchYear ? defaultCYYear() : (new Date()).getFullYear(); }
    catch { return (new Date()).getFullYear(); }
  });

  const scrollPageToTop = () => {
    document.querySelector('.page-body')?.scrollTo({ top: 0 });
  };

  // Sync state from browser back/forward
  useEffect(() => {
    const syncRoute = () => {
      const { view: v, series: s, sunday: sun, resourceSetId: rsid } = parsePath(window.location.pathname);
      setView(v);
      setSeries(s);
      setSelectedIdx(sun);
      setResourceSetId(rsid ?? null);
      scrollPageToTop();
    };
    window.addEventListener('popstate', syncRoute);
    return () => window.removeEventListener('popstate', syncRoute);
  }, []);

  // Core navigation: push a history entry and update state
  const navigate = useCallback((newView, newSeries, newSunday) => {
    const s = newSeries ?? series;
    window.history.pushState(null, '', buildPath({ view: newView, series: s, sunday: newSunday ?? null }));
    setView(newView);
    setSeries(s);
    setSelectedIdx(newSunday ?? null);
    setResourceSetId(null);
    scrollPageToTop();
  }, [series]);

  // Navigate to a resource set detail page
  const navigateToResourceSet = useCallback((setId) => {
    window.history.pushState(null, '', buildPath({ view: 'resources', resourceSetId: setId }));
    setView('resources');
    setResourceSetId(setId);
    scrollPageToTop();
  }, []);

  const entries = window.LECTIONARY_DATA[series] || [];
  const seriesLabel = SERIES_LABELS[series] || series;

  // Currently-selected entry
  const selectedEntry = selectedIdx != null ? entries[selectedIdx] : null;
  const selectedSeason = selectedEntry ? window.LSB_seasonFor(selectedEntry.Sunday) : null;

  useEffect(() => {
    document.title = buildDocumentTitle({ view, series, selectedEntry, resourceSetId });
  }, [view, series, selectedEntry, resourceSetId]);

  // Curated resource-set items that reference this Sunday
  const sundayPath = selectedEntry
    ? buildPath({ view: 'lectionary', series, sunday: selectedIdx })
    : null;
  const curatedResources = useMemo(() => {
    if (!sundayPath || !window.RESOURCE_SETS) return [];
    const out = [];
    window.RESOURCE_SETS.forEach((set) => {
      set.resources.forEach((res) => {
        if (res.sundays && res.sundays.includes(sundayPath)) {
          out.push({ ...res, _setTitle: set.title, _setId: set.id });
        }
      });
    });
    return out;
  }, [sundayPath]);

  // Season groups (for filter chips)
  const allSeasonGroups = useMemo(() => window.LSB_groupBySeason(entries), [entries]);

  const handleView = (v) => navigate(v, series, null);

  const handleNextSunday = () => {
    const next = findNextSunday();
    if (next) navigate('lectionary', next.seriesId, next.idx);
    else navigate('lectionary', series, null);
  };

  const handleSeries = (s) => {
    setQuery('');
    setActiveSeasons([]);
    navigate('lectionary', s, null);
  };

  const handleSelect = (idx) => navigate('lectionary', series, idx);
  const handleBack = () => navigate('lectionary', series, null);
  const openSundayFromLibrary = (seriesId, idx) => navigate('lectionary', seriesId, idx);

  // Navigate to a Sunday given its canonical path (e.g. /lectionary/three-year-a/holy-trinity)
  const handleOpenSundayFromPath = (path) => {
    const { view: v, series: s, sunday: sun } = parsePath(path);
    navigate(v, s, sun);
  };

  const goPrev = useCallback(() => {
    if (selectedIdx == null) return;
    const ni = selectedIdx - 1;
    if (ni >= 0) navigate('lectionary', series, ni);
  }, [selectedIdx, series, navigate]);

  const goNext = useCallback(() => {
    if (selectedIdx == null) return;
    const ni = selectedIdx + 1;
    if (ni < entries.length) navigate('lectionary', series, ni);
  }, [selectedIdx, series, entries.length, navigate]);

  // Keyboard nav inside detail
  useEffect(() => {
    if (selectedIdx == null) return;
    const onKey = (e) => {
      if (e.target.tagName === 'INPUT' || e.target.tagName === 'TEXTAREA') return;
      if (scriptureModal) return;
      if (e.key === 'ArrowLeft') goPrev();
      else if (e.key === 'ArrowRight') goNext();
      else if (e.key === 'Escape') handleBack();
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [selectedIdx, goPrev, goNext, scriptureModal]);

  const toggleSeason = (id) => {
    setActiveSeasons((s) => s.includes(id) ? s.filter((x) => x !== id) : [...s, id]);
  };

  const renderLectionary = () => {
    if (selectedEntry) {
      return (
        <SundayDetail
          entry={selectedEntry}
          season={selectedSeason}
          seriesLabel={seriesLabel}
          onBack={handleBack}
          onPrev={goPrev}
          onNext={goNext}
          hasPrev={selectedIdx > 0}
          hasNext={selectedIdx < entries.length - 1}
          curatedResources={curatedResources}
          onShowScripture={(reading) => setScriptureModal(reading)}
        />
      );
    }
    return (
      <>
        <FilterBar
          series={series}
          onSeries={handleSeries}
          query={query}
          onQuery={setQuery}
          activeSeasons={activeSeasons}
          onToggleSeason={toggleSeason}
          seasonGroups={allSeasonGroups}
          totalCount={entries.length}
          visibleCount={countVisible(entries, query, activeSeasons)}
        />
        <main className="main">
          <IndexView
            entries={entries}
            seriesId={series}
            query={query}
            activeSeasons={activeSeasons}
            onSelect={handleSelect}
          />
        </main>
      </>
    );
  };

  return (
    <div className="app">
      <Banner
        view={view}
        onView={handleView}
        series={series}
        onSeries={handleSeries}
        onNextSunday={handleNextSunday}
      />

      <div className="page-body">
        {view === 'lectionary' && renderLectionary()}
        {view === 'resources' && (
          <main className="main main--flush">
            {resourceSetId ? (
              <ResourceSetView
                setId={resourceSetId}
                onBack={() => navigate('resources', series, null)}
                onOpenSunday={handleOpenSundayFromPath}
              />
            ) : (
              <ResourcesView
                onOpenSet={navigateToResourceSet}
              />
            )}
          </main>
        )}
        {view === 'church-year' && (
          <main className="main main--flush">
            <ChurchYearView
              year={cyYear}
              onYear={setCYYear}
              seriesForm={cySeriesForm}
              onSeriesForm={setCYSeriesForm}
              onOpenSunday={openSundayFromLibrary}
            />
          </main>
        )}
        {view === 'about' && (
          <main className="main">
            <BlankPage
              title="About"
              subtitle="A companion to the Lutheran Service Book lectionary."
              body={(
                <>
                  <p>
                    A lectionary is a collection of Scripture readings arranged
                    according to the church calendar, intended to be read at the
                    regular, weekly gathering of God's people. Already in the
                    fourth century, readings were gathered together for this
                    purpose. The lectionary gives the church a path through
                    Scripture: week by week, season by season, from Advent
                    through Pentecost and back again.
                  </p>
                  <p>
                    This site is built to help you walk that path. First, it
                    helps you explore the lectionary itself, the readings, their
                    context, and how they fit the church year. Second, it
                    gathers together a wide range of outside resources and
                    organizes them around that same calendar. Hymns, prayers,
                    images, songs, devotions: things that connect us to
                    Scripture and to the seasons of the church year, brought
                    together in one place so they're easier to find and use.
                  </p>
                  <p>
                    The materials here support the lectionary used by the
                    Lutheran Church–Missouri Synod. The LCMS Three-Year
                    Lectionary follows the general shape of the Revised Common
                    Lectionary, while making small changes where the church
                    judged it important to hear theologically significant texts.
                    Though the RCL was not adopted in its entirety, the
                    Three-Year Lectionary for Lutheran Service Book is in
                    agreement with the RCL the vast majority of the time.
                  </p>
                  <p>
                    <em>
                      The resources linked and collected here come from a
                      variety of sources and reflect the curator's judgment, not
                      a denominational endorsement.
                    </em>
                  </p>
                </>
              )}
            />
          </main>
        )}
        {view === 'copyright' && (
          <main className="main">
            <BlankPage
              title="Copyright Notices"
              subtitle="ESV Bible"
              body={(
                <>
                  <p>
                    Scripture quotations are from the ESV® Bible (The Holy
                    Bible, English Standard Version®), © 2001 by Crossway, a
                    publishing ministry of Good News Publishers. Used by
                    permission. All rights reserved. The ESV text may not be
                    quoted in any publication made available to the public by a
                    Creative Commons license. The ESV may not be translated into
                    any other language.
                  </p>
                  <p>
                    Users may not copy or download more than 500 verses of the
                    ESV Bible or more than one half of any book of the ESV
                    Bible.
                  </p>
                </>
              )}
            />
          </main>
        )}

        {scriptureModal && (
          <ScriptureModal
            reading={scriptureModal}
            onClose={() => setScriptureModal(null)}
          />
        )}

        <footer className="site-footer">
          <span>
            A companion to the <em>Lutheran Service Book</em> lectionary. This is an unofficial resource and not affiliated with or endorsed by the Lutheran Church—Missouri Synod.
          </span>
        </footer>
      </div>
    </div>
  );
}

function countVisible(entries, query, activeSeasons) {
  const q = query.trim().toLowerCase();
  return entries.filter((e) => {
    if (activeSeasons.length) {
      const s = window.LSB_seasonFor(e.Sunday);
      if (!activeSeasons.includes(s.id)) return false;
    }
    if (!q) return true;
    return (
      e.Sunday.toLowerCase().includes(q) ||
      (e['Old Testament'] || '').toLowerCase().includes(q) ||
      (e.Epistle || '').toLowerCase().includes(q) ||
      (e.Gospel || '').toLowerCase().includes(q) ||
      (e.Psalm || '').toLowerCase().includes(q)
    );
  }).length;
}

async function init() {
  const urls = window.RESOURCE_SET_URLS || [];
  const results = await Promise.all(
    urls.map(url => fetch(url).then(r => r.json()).catch(() => null))
  );
  window.RESOURCE_SETS = results.filter(Boolean);

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

init();
