/**
 * SchoolDetailShell — the interactive chrome of a school detail page.
 *
 * The ONLY large client component on the route. Everything below the sticky
 * nav is server-rendered and arrives as `children`, composed in
 * app/school/[slug]/page.tsx. That indirection is required: a server component
 * imported by a client component becomes a client component, so the sections
 * cannot be imported here.
 *
 * What stays client-side is genuinely interactive: router.back(), the header
 * details reveal, the hero map, the compare CTA, the nav overflow fade, the
 * Escape-to-close jump sheet, and the scroll-spy. The scroll-spy finds
 * sections with document.getElementById, so it works unchanged against
 * server-rendered children.
 */

'use client';

import { useEffect, useRef, useState, type ReactNode } from 'react';
import { useRouter } from 'next/navigation';
import { useComparison } from '@/hooks/useComparison';
import { SchoolHeroMap, type SchoolHeroMapHandle } from '../SchoolHeroMap';
import type { School, SchoolResult, SchoolCensus } from '@/lib/types';
import { formatAgeRange, isProposedToClose } from '@/lib/utils';
import type { NavItem } from '@/lib/schoolSections';
import { track, getNavigationSource } from '@/lib/analytics';
import styles from './SchoolDetailShell.module.css';


/**
 * Only what the chrome itself renders. Everything the sections need — Ofsted,
 * admissions, deprivation, finance, national averages — goes straight to the
 * section composers in page.tsx and never reaches the client.
 */
export interface SchoolDetailShellProps {
  schoolInfo: School;
  /** Only for the header's pupil-count fallback. */
  yearlyData: SchoolResult[];
  census: SchoolCensus | null;
  /** Section list for the sticky nav, computed on the server. */
  navItems: NavItem[];
  /** The server-rendered sections. */
  children: ReactNode;
}

export function SchoolDetailShell({
  schoolInfo, yearlyData, census, navItems, children,
}: SchoolDetailShellProps) {
  const router = useRouter();
  const { addSchool, removeSchool, isSelected } = useComparison();
  const isInComparison = isSelected(schoolInfo.urn);

  const [activeSection, setActiveSection] = useState<string>('');
  // Admissions view state moved to AdmissionsViewToggle, the client island
  // inside the (server-rendered) admissions section.
  // Only the section links scroll horizontally; Back and "All" stay pinned.
  const sectionLinksRef = useRef<HTMLDivElement | null>(null);
  const [sectionNavAtEnd, setSectionNavAtEnd] = useState(false);
  // Carry the "Add to Compare" CTA into the sticky bar once the hero's button leaves.
  const heroActionsRef = useRef<HTMLDivElement | null>(null);
  const [heroCtaVisible, setHeroCtaVisible] = useState(true);
  // Hero map — the "View on map" link opens its fullscreen view.
  const heroMapRef = useRef<SchoolHeroMapHandle>(null);
  // "All ▾" jump menu listing every section.
  const [sectionsOpen, setSectionsOpen] = useState(false);
  // Header details (headteacher, contact, trust, area) collapse behind a
  // "Show all details" link on mobile/tablet, where they're below the fold.
  const [detailsOpen, setDetailsOpen] = useState(false);

  // Back returns to wherever the user came from; deep-links (no in-app history)
  // fall back to search so the button never dead-ends or leaves the site.
  const handleBack = () => {
    if (typeof window !== 'undefined' && window.history.length > 1) {
      router.back();
    } else {
      router.push('/search');
    }
  };

  const scrollToTop = () => {
    if (typeof window !== 'undefined') window.scrollTo({ top: 0, behavior: 'smooth' });
  };

  useEffect(() => {
    const el = sectionLinksRef.current;
    if (!el) return;
    const update = () => {
      const overflow = el.scrollWidth - el.clientWidth;
      // No overflow → treat as "at end" so the fade is hidden.
      if (overflow <= 1) {
        setSectionNavAtEnd(true);
        return;
      }
      setSectionNavAtEnd(el.scrollLeft >= overflow - 2);
    };
    update();
    el.addEventListener('scroll', update, { passive: true });
    window.addEventListener('resize', update);
    return () => {
      el.removeEventListener('scroll', update);
      window.removeEventListener('resize', update);
    };
  }, []);

  // Track whether the hero's "Add to Compare" button is still on screen.
  useEffect(() => {
    const el = heroActionsRef.current;
    if (!el) return;
    const obs = new IntersectionObserver(
      ([entry]) => setHeroCtaVisible(entry.isIntersecting),
      { rootMargin: '-64px 0px 0px 0px' },
    );
    obs.observe(el);
    return () => obs.disconnect();
  }, []);

  // Close the "All ▾" menu on Escape.
  useEffect(() => {
    if (!sectionsOpen) return;
    const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') setSectionsOpen(false); };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [sectionsOpen]);

  // The chrome needs only these four. The section-shape flags are computed
  // once on the server (lib/schoolSections) and consumed by the section
  // composers; recomputing them here would duplicate that work for values
  // this component never renders.
  const latestResults = yearlyData.length > 0 ? yearlyData[yearlyData.length - 1] : null;
  const phase = schoolInfo.phase ?? '';
  const isAllThrough = phase.toLowerCase() === 'all-through';
  const hasLocation = schoolInfo.latitude != null && schoolInfo.longitude != null;

  const handleComparisonToggle = () => {
    if (isInComparison) {
      removeSchool(schoolInfo.urn);
      track('compare_school_removed', { urn: schoolInfo.urn, from: 'detail' });
    } else {
      addSchool(schoolInfo);
      track('compare_school_added', { urn: schoolInfo.urn, from: 'detail' });
    }
  };

  // Page-view event with funnel attribution. Fires once per mount.
  useEffect(() => {
    track('school_viewed', {
      urn: schoolInfo.urn,
      phase: phase || 'unknown',
      local_authority: schoolInfo.local_authority || 'unknown',
      from: getNavigationSource(),
    });
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [schoolInfo.urn]);

  // Track active section as user scrolls
  useEffect(() => {
    const ids = navItems.map(n => n.id);
    if (!ids.length) return;

    const observers: IntersectionObserver[] = [];
    const ratioMap: Record<string, number> = {};

    const pickActive = () => {
      const top = Object.entries(ratioMap).sort((a, b) => b[1] - a[1])[0];
      setActiveSection(top?.[1] > 0 ? top[0] : '');
    };

    ids.forEach(id => {
      const el = document.getElementById(id);
      if (!el) return;
      ratioMap[id] = 0;
      const obs = new IntersectionObserver(
        ([entry]) => {
          ratioMap[id] = entry.intersectionRatio;
          pickActive();
        },
        { threshold: [0, 0.1, 0.25, 0.5, 0.75, 1.0], rootMargin: '-56px 0px 0px 0px' },
      );
      obs.observe(el);
      observers.push(obs);
    });

    return () => observers.forEach(o => o.disconnect());
  // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [navItems.map(n => n.id).join(',')]);

  // Label shown in the mobile "section" menu button — the section in view.
  const activeNavLabel = (navItems.find((n) => n.id === activeSection) ?? navItems[0])?.label ?? '';

  return (
    <div className={styles.container}>
      {/* Standalone back link, above the header — returns to wherever the
          user came from. Scrolls away with the page (the sticky bar keeps a
          "back to top" control in its place). */}
      <button type="button" onClick={handleBack} className={styles.topBack}>
        <span aria-hidden="true">←</span> Back
      </button>

      {/* Header — the location map band blends down into the school title. */}
      <header className={`${styles.header}${hasLocation ? ` ${styles.headerHasMap}` : ''}`}>
        {hasLocation && (
          <SchoolHeroMap ref={heroMapRef} lat={schoolInfo.latitude!} lng={schoolInfo.longitude!} />
        )}
        <div className={styles.headerContent}>
          <div className={styles.titleSection}>
            <h1 className={styles.schoolName}>{schoolInfo.school_name}</h1>
            <div className={styles.meta}>
              {schoolInfo.local_authority && (
                <span className={styles.metaItem}>{schoolInfo.local_authority}</span>
              )}
              {schoolInfo.school_type && (
                <span className={styles.metaItem}>{schoolInfo.school_type}</span>
              )}
              {isAllThrough && (
                <span className={styles.metaItem}>All-through (primary &amp; secondary)</span>
              )}
              {schoolInfo.gender && schoolInfo.gender !== 'Mixed' && (
                <span className={styles.metaItem}>{schoolInfo.gender}&apos;s school</span>
              )}
              {schoolInfo.age_range && (
                <span className={styles.metaItem}>{formatAgeRange(schoolInfo.age_range)}</span>
              )}
              {schoolInfo.nursery_provision && (
                <span className={styles.metaItem}>Nursery</span>
              )}
              {schoolInfo.has_sixth_form && (
                <span className={styles.metaItem}>Sixth form</span>
              )}
            </div>
            {isProposedToClose(schoolInfo) && (
              <div className={styles.closingStrip} role="note">
                <strong>⚠ Proposed to close</strong> — this school is proposed for closure,
                check with the local authority before applying.
              </div>
            )}
            {schoolInfo.address && (
              <p className={styles.address}>
                {schoolInfo.address}{schoolInfo.postcode && `, ${schoolInfo.postcode}`}
                {hasLocation && (
                  <>
                    {' · '}
                    <button
                      type="button"
                      className={styles.mapLink}
                      onClick={() => { heroMapRef.current?.open(); track('section_nav_used', { section: 'location', via: 'hero_link' }); }}
                    >
                      View on map ↗
                    </button>
                  </>
                )}
              </p>
            )}
            <button
              type="button"
              className={styles.detailsToggle}
              aria-expanded={detailsOpen}
              aria-controls="school-header-details"
              onClick={() => setDetailsOpen((o) => !o)}
            >
              {detailsOpen ? 'Hide details' : 'Show all details'}
              <span aria-hidden="true">{detailsOpen ? '▴' : '▾'}</span>
            </button>
            <div
              id="school-header-details"
              className={`${styles.headerDetails}${detailsOpen ? ` ${styles.headerDetailsOpen}` : ''}`}
            >
              {schoolInfo.headteacher_name && (
                <span className={styles.headerDetail}>
                  <strong>Headteacher:</strong> {schoolInfo.headteacher_name}
                </span>
              )}
              {schoolInfo.website && (
                <span className={styles.headerDetail}>
                  <a
                    href={/^https?:\/\//i.test(schoolInfo.website) ? schoolInfo.website : `https://${schoolInfo.website}`}
                    target="_blank"
                    rel="noopener noreferrer"
                    data-umami-event="external_link_clicked"
                    data-umami-event-target="school_website"
                  >
                    School website ↗
                  </a>
                </span>
              )}
              {(() => {
                const total = census?.total_pupils ?? latestResults?.total_pupils ?? null;
                if (total == null) return null;
                return (
                  <span className={styles.headerDetail}>
                    <strong>Pupils:</strong> {total.toLocaleString()}
                    {schoolInfo.capacity != null && ` (capacity: ${schoolInfo.capacity})`}
                  </span>
                );
              })()}
              {schoolInfo.trust_name && (
                <span className={styles.headerDetail}>
                  Part of <strong>{schoolInfo.trust_name}</strong>
                </span>
              )}
              {schoolInfo.telephone && (
                <span className={styles.headerDetail}>
                  <strong>Phone:</strong>{' '}
                  <a href={`tel:${schoolInfo.telephone.replace(/\s+/g, '')}`}>
                    {schoolInfo.telephone}
                  </a>
                </span>
              )}
              {schoolInfo.religious_denomination && (
                <span className={styles.headerDetail}>
                  <strong>Religious character:</strong>{' '}
                  {['Does not apply', 'None'].includes(schoolInfo.religious_denomination)
                    ? 'None'
                    : schoolInfo.religious_denomination}
                </span>
              )}
              {schoolInfo.county && (
                <span className={styles.headerDetail}>
                  <strong>County:</strong> {schoolInfo.county}
                </span>
              )}
              {schoolInfo.parliamentary_constituency && (
                <span className={styles.headerDetail}>
                  <strong>Constituency:</strong> {schoolInfo.parliamentary_constituency}
                </span>
              )}
            </div>
          </div>
          <div className={styles.actions} ref={heroActionsRef}>
            <button
              onClick={handleComparisonToggle}
              className={isInComparison ? styles.btnRemove : styles.btnAdd}
              aria-label={isInComparison ? 'In comparison' : 'Add to compare'}
            >
              {/* On phones the map hero shows only the glyph (nav-bar style). */}
              <span className={styles.btnCompareLabel}>
                {isInComparison ? '✓ In Comparison' : '+ Add to Compare'}
              </span>
              <span className={styles.btnCompareGlyph} aria-hidden="true">
                {isInComparison ? '✓' : '+'}
              </span>
            </button>
          </div>
        </div>
      </header>

      {/* Sticky Section Navigation — docks under the global header */}
      <nav className={styles.sectionNav} aria-label="Page sections">
        <button onClick={scrollToTop} className={styles.sectionNavBack} aria-label="Back to top">
          <span aria-hidden="true">↑</span>
          <span className={styles.sectionNavBackLabel}>Top</span>
        </button>

        {/* Desktop: scrolling section links */}
        <div
          ref={sectionLinksRef}
          className={`${styles.sectionNavLinks}${sectionNavAtEnd ? ` ${styles.atEnd}` : ''}`}
        >
          {navItems.map(({ id, label }) => (
            <a
              key={id}
              href={`#${id}`}
              className={`${styles.sectionNavLink}${activeSection === id ? ` ${styles.sectionNavLinkActive}` : ''}`}
              onClick={() => track('section_nav_used', { section: id })}
            >
              {label}
            </a>
          ))}
        </div>

        {/* Mobile: a single "section" menu button that opens the jump sheet */}
        {navItems.length > 0 && (
          <button
            type="button"
            className={styles.sectionNavMenu}
            aria-haspopup="menu"
            aria-expanded={sectionsOpen}
            onClick={() => setSectionsOpen((o) => !o)}
          >
            <span className={styles.sectionNavMenuCur}>
              <span className={styles.sectionNavMenuEyebrow}>Section</span>
              <span className={styles.sectionNavMenuNow}>{activeNavLabel}</span>
            </span>
            <span className={styles.sectionNavMenuChev} aria-hidden="true">▾</span>
          </button>
        )}

        {/* The hero's Compare CTA, carried in once it scrolls out of view.
            Desktop shows a labelled pill; mobile a compact icon. */}
        {!heroCtaVisible && (
          <>
            <button
              onClick={handleComparisonToggle}
              className={`${styles.sectionNavCompare}${isInComparison ? ` ${styles.sectionNavCompareIn}` : ''}`}
            >
              {isInComparison ? '✓ Comparing' : '+ Compare'}
            </button>
            <button
              onClick={handleComparisonToggle}
              className={`${styles.sectionNavCompareIcon}${isInComparison ? ` ${styles.sectionNavCompareIconIn}` : ''}`}
              aria-label={isInComparison ? 'In comparison' : 'Add to compare'}
              title={isInComparison ? 'In comparison' : 'Add to compare'}
            >
              {isInComparison ? (
                <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
                  <path d="m5 12 5 5 9-11" />
                </svg>
              ) : (
                <>
                  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" aria-hidden="true">
                    <path d="M4 7h13l-3-3" />
                    <path d="M20 17H7l3 3" />
                  </svg>
                  <span className={styles.sectionNavCompareBadge} aria-hidden="true">+</span>
                </>
              )}
            </button>
          </>
        )}

        {/* Desktop: "All ▾" trigger (same sheet as the mobile section menu) */}
        {navItems.length > 0 && (
          <button
            type="button"
            className={styles.sectionNavAll}
            aria-haspopup="menu"
            aria-expanded={sectionsOpen}
            onClick={() => setSectionsOpen((o) => !o)}
          >
            All <span aria-hidden="true">▾</span>
          </button>
        )}

        {/* Shared jump-to-section sheet (dropdown on desktop, bottom sheet on mobile) */}
        {sectionsOpen && (
          <>
            <div className={styles.sectionsBackdrop} onClick={() => setSectionsOpen(false)} />
            <div className={styles.sectionsPanel} role="menu" aria-label="Jump to section">
              <div className={styles.sectionsPanelHead}>Jump to section</div>
              {navItems.map(({ id, label }) => (
                <a
                  key={id}
                  href={`#${id}`}
                  role="menuitem"
                  className={`${styles.sectionsItem}${activeSection === id ? ` ${styles.sectionsItemActive}` : ''}`}
                  onClick={() => {
                    setSectionsOpen(false);
                    track('section_nav_used', { section: id, via: 'all_menu' });
                  }}
                >
                  <span>{label}</span>
                  {activeSection === id && <span className={styles.sectionsTick} aria-hidden="true">✓</span>}
                </a>
              ))}
            </div>
          </>
        )}
      </nav>

      {children}
    </div>
  );
}
