
const { useState, useEffect, useMemo } = React;

const API_BASE = 'https://transfer-lens.onrender.com';

// ── Data fetching hook ────────────────────────────────────────────────────────
function useApi(path) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState(null);

  useEffect(() => {
    if (!path) { setData(null); setLoading(false); setError(null); return; }
    let cancelled = false;
    setLoading(true);
    setError(null);
    fetch(API_BASE + path)
      .then(r => r.ok ? r.json() : Promise.reject(`HTTP ${r.status}`))
      .then(d => { if (!cancelled) { setData(d); setLoading(false); } })
      .catch(e => { if (!cancelled) { setError(String(e)); setLoading(false); } });
    return () => { cancelled = true; };
  }, [path]);

  return { data, loading, error };
}

// ── Shared loading / empty states ─────────────────────────────────────────────
function Spinner() {
  return (
    <div style={{ padding: '28px', textAlign: 'center', color: 'var(--text-3)' }}>
      <svg width="22" height="22" viewBox="0 0 22 22" fill="none"
        style={{ animation: 'pulse 1.1s ease-in-out infinite', display: 'inline-block' }}>
        <circle cx="11" cy="11" r="8" stroke="var(--accent)" strokeWidth="2.5"
          strokeDasharray="38 14" strokeLinecap="round"/>
      </svg>
    </div>
  );
}

function EmptyState({ message }) {
  return (
    <div style={{ padding: '16px 0', fontSize: '0.85rem', color: 'var(--text-3)' }}>
      {message}
    </div>
  );
}

// ── Articulation row — handles Course and Series requirement types ─────────────
function ArticRow({ req, inPlan, onAddToPlan }) {
  const artic = req.articulation;
  const articulated = artic && artic.articulated;

  // Build left-side label from receiving_courses or series_name
  let ucLabel;
  if (req.type === 'Series' && req.series_name) {
    ucLabel = req.series_name;
  } else if (req.receiving_courses && req.receiving_courses.length > 0) {
    const rc = req.receiving_courses[0];
    ucLabel = `${rc.prefix} ${rc.number} – ${rc.title}`;
  } else {
    ucLabel = '—';
  }

  // Filter out empty course groups (groups with no sending courses)
  const nonEmptyGroups = artic
    ? artic.course_groups.filter(g => g.courses && g.courses.length > 0)
    : [];

  const hasIvcCourses = articulated && nonEmptyGroups.length > 0;

  return (
    <div className={`artic-row ${!hasIvcCourses ? 'no-artic' : ''}`}>
      {/* Left: receiving school course */}
      <div className="artic-uc-side">
        <div className="artic-uc-course">{ucLabel}</div>
        <div className={`artic-status-dot ${hasIvcCourses ? 'ok' : 'none'}`}></div>
      </div>

      {/* Arrow */}
      <div className="artic-arrow">
        {hasIvcCourses
          ? <svg width="20" height="20" viewBox="0 0 20 20" fill="none">
              <path d="M4 10h12M12 6l4 4-4 4" stroke="var(--green)" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round"/>
            </svg>
          : <svg width="20" height="20" viewBox="0 0 20 20" fill="none">
              <path d="M6 6l8 8M14 6l-8 8" stroke="var(--red)" strokeWidth="1.8" strokeLinecap="round"/>
            </svg>
        }
      </div>

      {/* Right: IVC sending courses */}
      <div className="artic-ivc-side">
        {hasIvcCourses ? (
          nonEmptyGroups.map((group, gi) => (
            <div key={gi} className="artic-ivc-group">
              {gi > 0 && (
                <span className="artic-or-badge">
                  {(nonEmptyGroups[gi].group_conjunction || 'OR').toUpperCase()}
                </span>
              )}
              {group.courses.map((c, ci) => {
                const courseKey = `${c.prefix} ${c.number}`;
                const placed = inPlan.has(courseKey);
                return (
                  <div key={ci} className="artic-ivc-course">
                    {ci > 0 && (
                      <span className="artic-and-badge">
                        {(group.course_conjunction || 'AND').toUpperCase()}
                      </span>
                    )}
                    <div className="artic-ivc-chip">
                      <span className="artic-ivc-key">{courseKey}</span>
                      {c.title && <span className="artic-ivc-title">{c.title}</span>}
                      <span className="artic-ivc-units">{c.min_units}u</span>
                      {placed
                        ? <span className="artic-in-plan-badge">✓ In plan</span>
                        : <button className="artic-add-btn" onClick={() => onAddToPlan(courseKey, c)}>+ Add to plan</button>
                      }
                    </div>
                  </div>
                );
              })}
            </div>
          ))
        ) : (
          <div className="artic-no-equiv">
            <span className="artic-no-badge">No IVC equivalent</span>
            <span className="artic-no-note">
              {artic?.no_articulation_reason || 'Complete at the receiving school'}
            </span>
          </div>
        )}
      </div>
    </div>
  );
}

// ── Articulation view ─────────────────────────────────────────────────────────
function ArticulationView({ major, institution, data, inPlan, onAddToPlan, onBack }) {
  if (!data || !data.requirements) {
    return (
      <div className="artic-no-data">
        <div className="artic-no-data-icon">
          <svg width="40" height="40" viewBox="0 0 40 40" fill="none">
            <circle cx="20" cy="20" r="16" stroke="var(--divider)" strokeWidth="2"/>
            <path d="M20 12v9M20 26v2" stroke="var(--text-3)" strokeWidth="2" strokeLinecap="round"/>
          </svg>
        </div>
        <div className="artic-no-data-title">No articulation data yet</div>
        <div className="artic-no-data-sub">
          We're working on adding more school and major combinations. Check back soon, or try a different school.
        </div>
        <button className="btn-ghost" onClick={onBack}>← Choose a different school</button>
      </div>
    );
  }

  const { requirements, stats } = data;

  // Walk requirements in order, emitting section headers for 'Requirement' type
  // and ArticRows for 'Course'/'Series' types
  const sections = [];
  let currentSection = { header: null, reqs: [] };
  for (const req of requirements) {
    if (req.type === 'Requirement') {
      if (currentSection.reqs.length > 0 || currentSection.header) {
        sections.push(currentSection);
      }
      currentSection = { header: req.group_label, reqs: [] };
    } else {
      currentSection.reqs.push(req);
    }
  }
  if (currentSection.reqs.length > 0 || currentSection.header) {
    sections.push(currentSection);
  }
  // If no sections were created (all requirements have no 'Requirement' headers),
  // treat everything as one unlabeled section
  if (sections.length === 0) {
    sections.push({ header: null, reqs: requirements.filter(r => r.type !== 'Requirement') });
  }

  return (
    <div className="artic-view">
      <button className="btn-back" onClick={onBack}>← Back to schools</button>
      <div className="artic-hero">
        <div className="artic-hero-school">{institution.name}</div>
        <div className="artic-hero-major">{major.label}</div>
        <div className="artic-hero-stats">
          <span className="artic-stat ok">{stats.articulated} of {stats.total} requirements articulated</span>
          {stats.not_articulated > 0 && (
            <span className="artic-stat missing">{stats.not_articulated} require on-campus completion</span>
          )}
        </div>
      </div>

      <div className="artic-legend">
        <span className="artic-legend-item"><span className="legend-dot ok"></span>Articulated</span>
        <span className="artic-legend-item"><span className="legend-dot none"></span>No IVC equivalent</span>
      </div>

      {sections.map((section, si) => (
        section.reqs.length > 0 && (
          <div key={si} className="artic-section">
            <div className="artic-section-header">
              <span className="artic-section-title">
                {section.header || (si === 0 ? 'Required Preparation' : 'Additional Requirements')}
              </span>
              <span className="artic-section-count">{section.reqs.length} course{section.reqs.length !== 1 ? 's' : ''}</span>
            </div>
            <div className="artic-rows">
              {section.reqs.map(req => (
                <ArticRow key={req.id} req={req} inPlan={inPlan} onAddToPlan={onAddToPlan} />
              ))}
            </div>
          </div>
        )
      ))}
    </div>
  );
}

// ── Transfer view ─────────────────────────────────────────────────────────────
function TransferView({ profile, onUpdateProfile }) {
  const [selectedSchool, setSelectedSchool] = useState(null);
  const [selectedMajor, setSelectedMajor] = useState(null); // { id, label }
  const [schoolQuery, setSchoolQuery] = useState('');
  const [majorQuery, setMajorQuery] = useState('');
  const [showArtic, setShowArtic] = useState(false);
  const [articPath, setArticPath] = useState(null);

  // Fetch UC and CSU schools separately, in parallel
  const { data: ucSchools,  loading: ucLoading  } = useApi('/api/institutions?category=UC');
  const { data: csuSchools, loading: csuLoading } = useApi('/api/institutions?category=CSU');

  // Fetch majors once a school is selected
  const majorApiPath = selectedSchool ? `/api/institutions/${selectedSchool.id}/majors` : null;
  const { data: majors, loading: majorsLoading } = useApi(majorApiPath);

  // Fetch articulation only when the user clicks the CTA
  const { data: articData, loading: articLoading } = useApi(articPath);

  const inPlan = useMemo(() => {
    const keys = new Set(Object.values(profile.semesters || {}).flat());
    Object.keys(profile.courseStatuses || {}).forEach(k => keys.add(k));
    return keys;
  }, [profile]);

  const handleAddToPlan = (courseKey, courseData) => {
    // Inject into MOCK_COURSES so CourseCard can render it
    if (!window.MOCK_COURSES[courseKey] && courseData) {
      window.MOCK_COURSES[courseKey] = {
        title: courseData.title,
        units: courseData.min_units || 3,
        difficulty: 'medium',
        available: 'FS',
        prereqs: [],
      };
    }
    const sems = { ...profile.semesters };
    const semOrder = Object.keys(sems).sort();
    for (const sid of semOrder) {
      const courses = sems[sid] || [];
      if (courses.length < 5 && !courses.includes(courseKey)) {
        sems[sid] = [...courses, courseKey];
        onUpdateProfile({ semesters: sems });
        return;
      }
    }
  };

  const filterSchools = (schools) => {
    if (!schools) return [];
    if (!schoolQuery) return schools;
    const q = schoolQuery.toLowerCase();
    return schools.filter(s =>
      s.name.toLowerCase().includes(q) || s.code.toLowerCase().includes(q)
    );
  };

  const filteredMajors = useMemo(() => {
    if (!majors) return [];
    if (!majorQuery) return majors;
    const q = majorQuery.toLowerCase();
    return majors.filter(m => m.label.toLowerCase().includes(q));
  }, [majors, majorQuery]);

  const handleSelectSchool = (school) => {
    setSelectedSchool(school);
    setSelectedMajor(null);
    setMajorQuery('');
    setShowArtic(false);
    setArticPath(null);
  };

  const handleShowArtic = () => {
    setArticPath(`/api/majors/${selectedMajor.id}/articulation`);
    setShowArtic(true);
  };

  const handleBackToSchools = () => {
    setShowArtic(false);
    setSelectedMajor(null);
    setArticPath(null);
  };

  // Articulation screen
  if (showArtic && selectedSchool && selectedMajor) {
    return (
      <div className="transfer-view">
        {articLoading ? (
          <>
            <button className="btn-back" onClick={handleBackToSchools}>← Back to schools</button>
            <Spinner />
          </>
        ) : (
          <ArticulationView
            major={selectedMajor}
            institution={selectedSchool}
            data={articData}
            inPlan={inPlan}
            onAddToPlan={handleAddToPlan}
            onBack={handleBackToSchools}
          />
        )}
      </div>
    );
  }

  const schoolsLoading = ucLoading || csuLoading;
  const filteredUC  = filterSchools(ucSchools  || []);
  const filteredCSU = filterSchools(csuSchools || []);
  const noResults   = !schoolsLoading && filteredUC.length === 0 && filteredCSU.length === 0;

  return (
    <div className="transfer-view">
      <div className="transfer-intro">
        <h2 className="transfer-title">Transfer Requirements</h2>
        <p className="transfer-sub">Select a school and major to see which IVC courses satisfy each requirement.</p>
      </div>

      {/* ── Step 1: School ── */}
      <div className="transfer-step">
        <div className="transfer-step-label">1 · Target School</div>
        {selectedSchool ? (
          <div className="transfer-selected-row">
            <span className="transfer-selected-name">{selectedSchool.name}</span>
            <button className="btn-ghost-sm" onClick={() => handleSelectSchool(null)}>Change</button>
          </div>
        ) : (
          <>
            <div className="wiz-search-wrap" style={{ marginBottom: 12 }}>
              <svg className="wiz-search-icon" width="16" height="16" viewBox="0 0 16 16" fill="none">
                <circle cx="6.5" cy="6.5" r="4" stroke="currentColor" strokeWidth="1.5"/>
                <path d="M10 10l3 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
              </svg>
              <input className="wiz-search" placeholder="Search schools…"
                value={schoolQuery} onChange={e => setSchoolQuery(e.target.value)} />
            </div>

            {schoolsLoading ? <Spinner /> : noResults ? (
              <EmptyState message={`No schools match "${schoolQuery}"`} />
            ) : (
              <div className="transfer-school-grid">
                {filteredUC.length > 0 && (
                  <>
                    <div style={{
                      width: '100%', fontSize: '0.7rem', fontWeight: 700,
                      letterSpacing: '0.06em', textTransform: 'uppercase',
                      color: 'var(--text-3)', marginBottom: 4,
                    }}>UC System</div>
                    {filteredUC.map(s => (
                      <button key={s.id} className="transfer-school-btn" onClick={() => handleSelectSchool(s)}>
                        <span className="transfer-school-abbr">{s.code}</span>
                        <span className="transfer-school-type">UC · {s.major_count} majors</span>
                      </button>
                    ))}
                  </>
                )}

                {filteredUC.length > 0 && filteredCSU.length > 0 && (
                  <div style={{ width: '100%', height: 8 }} />
                )}

                {filteredCSU.length > 0 && (
                  <>
                    <div style={{
                      width: '100%', fontSize: '0.7rem', fontWeight: 700,
                      letterSpacing: '0.06em', textTransform: 'uppercase',
                      color: 'var(--text-3)', marginBottom: 4,
                    }}>CSU System</div>
                    {filteredCSU.map(s => (
                      <button key={s.id} className="transfer-school-btn" onClick={() => handleSelectSchool(s)}>
                        <span className="transfer-school-abbr">{s.code}</span>
                        <span className="transfer-school-type">CSU · {s.major_count} majors</span>
                      </button>
                    ))}
                  </>
                )}
              </div>
            )}
          </>
        )}
      </div>

      {/* ── Step 2: Major ── */}
      {selectedSchool && (
        <div className="transfer-step">
          <div className="transfer-step-label">2 · Major</div>
          {selectedMajor ? (
            <div className="transfer-selected-row">
              <span className="transfer-selected-name">{selectedMajor.label}</span>
              <button className="btn-ghost-sm" onClick={() => setSelectedMajor(null)}>Change</button>
            </div>
          ) : (
            <>
              <div className="wiz-search-wrap" style={{ marginBottom: 12 }}>
                <svg className="wiz-search-icon" width="16" height="16" viewBox="0 0 16 16" fill="none">
                  <circle cx="6.5" cy="6.5" r="4" stroke="currentColor" strokeWidth="1.5"/>
                  <path d="M10 10l3 3" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
                </svg>
                <input className="wiz-search" placeholder="Search majors…"
                  value={majorQuery} onChange={e => setMajorQuery(e.target.value)} autoFocus />
              </div>

              {majorsLoading ? <Spinner /> : filteredMajors.length === 0 ? (
                <EmptyState message={
                  majorQuery ? `No majors match "${majorQuery}"` : 'No majors available for this school'
                } />
              ) : (
                <div className="transfer-major-list">
                  {filteredMajors.map(m => (
                    <button key={m.id} className="transfer-major-btn" onClick={() => setSelectedMajor(m)}>
                      {m.label}
                      <svg width="14" height="14" viewBox="0 0 14 14" fill="none">
                        <path d="M5 3l4 4-4 4" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round"/>
                      </svg>
                    </button>
                  ))}
                </div>
              )}
            </>
          )}
        </div>
      )}

      {/* ── CTA ── */}
      {selectedSchool && selectedMajor && (
        <div className="transfer-cta">
          <button className="btn-primary-purple" onClick={handleShowArtic}>
            See articulation for {selectedSchool.code} · {selectedMajor.label} →
          </button>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { TransferView });
