// === Module 1 - Lesson 1.Q - Quiz (ANC Exam Bank) ===

const QUIZ_BANK = [
  // ── Cadru PM ──────────────────────────────────────────
  {
    q: "Care e diferența fundamentală între un proiect și o operațiune?",
    options: [
      "Proiectul costă mai mult decât o operațiune.",
      "Proiectul are un început și un sfârșit definite; operațiunile sunt repetitive.",
      "Proiectul e mai dificil decât o operațiune.",
      "Nu există diferență — sunt sinonime."
    ],
    correct: 1,
    cat: "Cadru PM",
    explain: "Proiectul e temporar și produce ceva unic. Operațiunile sunt repetitive și produc același output."
  },
  {
    q: "Un milestone (jalon) are durată?",
    options: [
      "Da, durata e dată de durata activităților precedente.",
      "Nu — milestone-ul are durată zero, e doar un punct pe timeline.",
      "Da, minim 1 zi.",
      "Depinde de tipul de proiect."
    ],
    correct: 1,
    cat: "Cadru PM",
    explain: "Milestone-ul e un eveniment — un punct de control, nu o activitate. Marchează un moment-cheie cu durată zero."
  },
  {
    q: "Carta proiectului (project charter) este elaborată în faza de:",
    options: ["Planificare", "Inițiere", "Execuție", "Închidere"],
    correct: 1,
    cat: "Cadru PM",
    explain: "Carta proiectului este documentul oficial de inițiere — sponsorul aprobă scopul și autoritatea PM-ului."
  },
  {
    q: "Cine autorizează formal un proiect prin semnarea cartei proiectului?",
    options: ["PM-ul", "Echipa de proiect", "Sponsorul proiectului", "Clientul final"],
    correct: 2,
    cat: "Cadru PM",
    explain: "Sponsorul deține autoritatea financiară și organizațională. PM-ul primește autoritate prin cartă, nu o acordă."
  },
  {
    q: "Ce definește cel mai bine un „livrabil” (deliverable)?",
    options: [
      "O activitate din planul de proiect",
      "Un produs, serviciu sau rezultat unic și verificabil",
      "O factură emisă clientului",
      "Un raport de status"
    ],
    correct: 1,
    cat: "Cadru PM",
    explain: "Livrabilul e output-ul tangibil al unei activități sau faze. Trebuie să fie verificabil — poți confirma că e complet."
  },
  {
    q: "Ciclul de viață al unui proiect cuprinde, în ordine:",
    options: [
      "Execuție → Planificare → Inițiere → Închidere",
      "Inițiere → Planificare → Execuție → Închidere",
      "Planificare → Inițiere → Execuție → Monitorizare",
      "Inițiere → Execuție → Planificare → Închidere"
    ],
    correct: 1,
    cat: "Cadru PM",
    explain: "Ordinea clasică PMBOK: Inițiere → Planificare → Execuție (cu Monitorizare & Control) → Închidere."
  },
  {
    q: "Triplul constraint cuprinde:",
    options: [
      "Echipă, Tehnologie, Documentație.",
      "Timp, Buget, Scope (sau Calitate).",
      "Sponsor, PM, Echipă.",
      "Cerințe, Design, Implementare."
    ],
    correct: 1,
    cat: "Cadru PM",
    explain: "Cele trei axe pe care un PM le balansează permanent. Optimizezi una, plătești cu celelalte două."
  },

  // ── Programare ────────────────────────────────────────
  {
    q: "Pe drumul critic, slack-ul activităților este:",
    options: [
      "Maxim (cel mai mare slack din proiect).",
      "Egal cu 0.",
      "Negativ.",
      "Egal cu durata proiectului."
    ],
    correct: 1,
    cat: "Programare",
    explain: "Activitățile critice au slack = 0. Orice întârziere pe ele întârzie întreg proiectul."
  },
  {
    q: "Diferența între crashing și fast-tracking?",
    options: [
      "Crashing taie scope; fast-tracking taie buget.",
      "Crashing alocă resurse extra (cost +); fast-tracking paralelizează activități (risc +).",
      "Sunt sinonime.",
      "Crashing se aplică doar la activități, fast-tracking la milestone-uri."
    ],
    correct: 1,
    cat: "Programare",
    explain: "Crashing = mai mulți oameni pe aceeași activitate, costă mai mult. Fast-tracking = activități în paralel care normal erau în serie, e mai riscant."
  },
  {
    q: "Activitate cu Early Start = 12, durată = 6, Late Finish = 22. Care e slack-ul?",
    options: ["0", "4", "6", "10"],
    correct: 1,
    cat: "Programare",
    explain: "EF = ES + durată = 18. LS = LF − durată = 16. Slack = LS − ES = 4."
  },
  {
    q: "Diagrama PERT diferă de Gantt prin:",
    options: [
      "PERT arată dependențe între activități; Gantt arată durate pe timeline",
      "Gantt arată dependențe; PERT arată durate",
      "Sunt echivalente",
      "PERT e doar pentru proiecte software"
    ],
    correct: 0,
    cat: "Programare",
    explain: "PERT = rețea de activități cu dependențe. Gantt = bare pe timeline. Complementare, nu echivalente."
  },
  {
    q: "Ce se întâmplă dacă o activitate de pe drumul critic întârzie cu 3 zile?",
    options: [
      "Nimic, slack-ul absoarbe întârzierea",
      "Proiectul întârzie cu exact 3 zile",
      "Doar faza curentă întârzie",
      "Se scurtează automat alte activități"
    ],
    correct: 1,
    cat: "Programare",
    explain: "Pe drumul critic, slack = 0. Orice întârziere se propagă 1:1 în durata totală a proiectului."
  },
  {
    q: "Lead time vs. lag time — care afirmație e corectă?",
    options: [
      "Lead = întârziere; Lag = devansare",
      "Lead = activitatea următoare începe mai devreme; Lag = începe mai târziu",
      "Sunt sinonime",
      "Lead se aplică doar la milestone-uri"
    ],
    correct: 1,
    cat: "Programare",
    explain: "Lead time = overlap (succesorul începe înainte ca predecesorul să termine). Lag = pauză impusă între activități."
  },
  {
    q: "Metoda CPM (Critical Path Method) presupune durate:",
    options: [
      "Probabilistice (3 estimări: optimist, pesimist, cel mai probabil)",
      "Deterministe (o singură valoare pe activitate)",
      "Aleatoare",
      "Egale pentru toate activitățile"
    ],
    correct: 1,
    cat: "Programare",
    explain: "CPM folosește durate fixe. PERT folosește 3 estimări probabilistice (optimist, pesimist, cel mai probabil)."
  },

  // ── Risc ──────────────────────────────────────────────
  {
    q: "Scope creep e o problemă pentru că:",
    options: [
      "Reduce calitatea livrabilelor.",
      "Crește scope-ul fără ajustarea de timp, buget, resurse.",
      "Demoralizează echipa.",
      "Toate de mai sus."
    ],
    correct: 3,
    cat: "Risc",
    explain: "Toate trei sunt consecințe reale. Dar definiția centrală e: creștere necontrolată fără re-baseline."
  },
  {
    q: "Care e diferența principală între risc și problemă (issue)?",
    options: [
      "Riscul costă mai mult",
      "Riscul e potențial, problema s-a materializat deja",
      "Sunt sinonime",
      "Riscul e extern, problema e internă"
    ],
    correct: 1,
    cat: "Risc",
    explain: "Risk = ceva ce S-AR PUTEA întâmpla. Issue = ceva ce S-A întâmplat deja. Tratare diferită."
  },
  {
    q: "Care opțiune NU e un răspuns standard la risc negativ?",
    options: ["Avoid (evitare)", "Mitigate (atenuare)", "Transfer", "Ignore (ignorare)"],
    correct: 3,
    cat: "Risc",
    explain: "Cele 4 strategii standard: Avoid, Mitigate, Transfer, Accept. Ignore nu e o strategie validă."
  },
  {
    q: "Gold plating se referă la:",
    options: [
      "Adăugarea de funcționalități nesolicitate de client",
      "Bugetul de rezervă în proiect",
      "Bonusurile pentru echipă",
      "Servicii premium pentru sponsor"
    ],
    correct: 0,
    cat: "Risc",
    explain: "Gold plating = echipa adaugă „extra” crezând că face bine. Periculos: timp + buget consumate pe valori nesolicitate."
  },
  {
    q: "Cea mai frecventă cauză a eșecului proiectelor, conform PMI, e:",
    options: [
      "Lipsa de buget",
      "Schimbarea cerințelor (scope creep)",
      "Echipa nepregătită",
      "Conflicte cu sponsorul"
    ],
    correct: 1,
    cat: "Risc",
    explain: "Scope creep — adăugarea necontrolată de cerințe — apare în 60-70% din proiectele eșuate."
  },
  {
    q: "Registrul de riscuri conține:",
    options: [
      "Doar riscurile negative",
      "Riscuri identificate, probabilitate, impact, strategie de răspuns și responsabil",
      "Doar riscurile cu impact financiar",
      "Lista problemelor deja întâmplate"
    ],
    correct: 1,
    cat: "Risc",
    explain: "Registrul e documentul viu al riscurilor: id, descriere, probabilitate, impact, strategie, owner. Include și oportunități."
  },
  {
    q: "Matricea probabilitate × impact servește la:",
    options: [
      "Calcularea bugetului de contingență",
      "Prioritizarea riscurilor pe baza severității lor",
      "Identificarea stakeholderilor",
      "Planificarea activităților"
    ],
    correct: 1,
    cat: "Risc",
    explain: "Heatmap-ul P×I clasifică riscurile în zone (roșu/galben/verde) pentru a decide unde aloci efort de mitigare."
  },

  // ── Organizare ────────────────────────────────────────
  {
    q: "Într-o organizație matriceală, fiecare angajat raportează la:",
    options: [
      "Un singur șef — managerul de departament.",
      "Doi șefi — managerul funcțional și PM-ul.",
      "Trei șefi — funcțional, PM, sponsor.",
      "Doar la sponsor."
    ],
    correct: 1,
    cat: "Organizare",
    explain: "Caracteristica esențială a matricei: dublu raport. De aceea necesită maturitate organizațională ca să funcționeze."
  },
  {
    q: "În RACI, „Accountable” înseamnă:",
    options: [
      "Persoana care face efectiv munca.",
      "Persoana care răspunde final pentru rezultat (un singur A per task).",
      "Persoana consultată în deciziile cheie.",
      "Persoana doar informată."
    ],
    correct: 1,
    cat: "Organizare",
    explain: "Accountable = răspunde cu capul. Regula: un singur A per activitate. Pot fi mai mulți R, C și I."
  },
  {
    q: "În organizația matriceală puternică, cine controlează resursele și bugetul proiectului?",
    options: ["Managerul funcțional", "PM-ul", "Sponsorul", "Echipa, prin consens"],
    correct: 1,
    cat: "Organizare",
    explain: "În matriceala puternică, PM-ul are autoritate principală. În matriceala slabă, managerul funcțional deține controlul."
  },
  {
    q: "Organizația funcțională (piramidală) are dezavantajul principal:",
    options: [
      "Nu are ierarhie clară",
      "Silo-uri departamentale — comunicare slabă între departamente",
      "PM-ul are prea multă putere",
      "E prea scumpă"
    ],
    correct: 1,
    cat: "Organizare",
    explain: "Structura funcțională creează silo-uri: fiecare departament lucrează izolat. Proiectele cross-funcționale suferă."
  },
  {
    q: "Într-o organizație projectizată (project-based), PM-ul are:",
    options: [
      "Autoritate minimă",
      "Autoritate partajată cu managerii funcționali",
      "Autoritate maximă asupra echipei și resurselor proiectului",
      "Doar rol consultativ"
    ],
    correct: 2,
    cat: "Organizare",
    explain: "În organizația projectizată, echipa lucrează 100% pe proiect, sub autoritatea directă a PM-ului."
  },
  {
    q: "În planul de comunicare, „Informed” în RACI înseamnă:",
    options: [
      "Stakeholderi care iau decizii",
      "Stakeholderi care primesc update-uri, dar nu acționează",
      "Stakeholderi consultați înainte de decizii",
      "Stakeholderii care fac munca"
    ],
    correct: 1,
    cat: "Organizare",
    explain: "Informed = doar primește notificări. Nu li se cere input, nu iau decizii. One-way communication."
  },

  // ── Instrumente ───────────────────────────────────────
  {
    q: "Pe matricea Eisenhower, sarcinile din cadranul Q2 (Important, NU urgent) trebuie:",
    options: [
      "Eliminate — nu sunt urgente.",
      "Delegate altcuiva.",
      "Planificate proactiv — aici trăiește un PM bun.",
      "Făcute imediat."
    ],
    correct: 2,
    cat: "Instrumente",
    explain: "Q2 e zona strategică: planificare, învățare, prevenție riscuri. Petrecut aici, reduci Q1 (criza) în viitor."
  },
  {
    q: "Matricea Eisenhower clasifică sarcinile după:",
    options: ["Cost și efort", "Urgență și importanță", "Buget și timp", "Risc și impact"],
    correct: 1,
    cat: "Instrumente",
    explain: "Cele două axe: urgență și importanță. Q1 fă, Q2 planifică, Q3 deleagă, Q4 elimină."
  },
  {
    q: "WBS (Work Breakdown Structure) e cel mai bine descris ca:",
    options: [
      "O listă plată de task-uri",
      "O ierarhie arborescentă a livrabilelor proiectului",
      "Un timeline cu dependențe",
      "O matrice de roluri"
    ],
    correct: 1,
    cat: "Instrumente",
    explain: "WBS = descompunere ierarhică. Rădăcină = proiectul. Frunze = pachetele de lucru. Regula 100% pe fiecare nivel."
  },
  {
    q: "În SWOT, „Bariere de intrare în industrie scăzute” se clasifică drept:",
    options: ["Strength", "Weakness", "Opportunity", "Threat"],
    correct: 3,
    cat: "Instrumente",
    explain: "Factor extern negativ — favorizează concurența nouă să intre pe piață. Threat."
  },
  {
    q: "Analiza SWOT combină factori interni și externi. Care sunt factorii interni?",
    options: [
      "Opportunities și Threats",
      "Strengths și Weaknesses",
      "Strengths și Opportunities",
      "Weaknesses și Threats"
    ],
    correct: 1,
    cat: "Instrumente",
    explain: "Interni = Strengths + Weaknesses (ce controlezi). Externi = Opportunities + Threats (mediul)."
  },
  {
    q: "Regula 100% în WBS înseamnă:",
    options: [
      "Fiecare activitate trebuie să aibă 100% resurse alocate",
      "Suma elementelor copil trebuie să acopere 100% din elementul părinte",
      "Bugetul trebuie alocat 100%",
      "Toate riscurile trebuie identificate"
    ],
    correct: 1,
    cat: "Instrumente",
    explain: "La fiecare nivel al WBS, elementele copil reprezintă integral (100%) elementul părinte. Nimic în plus, nimic în minus."
  },

  // ── Planificare ───────────────────────────────────────
  {
    q: "Obiectiv SMART — care literă lipsește: Specific, Measurable, ___, Relevant, Time-bound?",
    options: ["Achievable", "Advanced", "Accurate", "Actionable"],
    correct: 0,
    cat: "Planificare",
    explain: "Achievable = realizabil. Obiectivul nu trebuie să fie imposibil de atins cu resursele disponibile."
  },
  {
    q: "Care e principala sursă de informații pentru estimarea inițială a costurilor?",
    options: [
      "Sponsorul proiectului",
      "Lessons learned din proiecte similare anterioare",
      "Echipa juridică",
      "Auditorul extern"
    ],
    correct: 1,
    cat: "Planificare",
    explain: "Datele istorice (analogous estimating) sunt prima sursă. Apoi: bottom-up din WBS, expert judgment, parametric."
  },
  {
    q: "Care e diferența între beneficiar direct și beneficiar indirect?",
    options: [
      "Beneficiarul direct e mai important",
      "Direct primește livrabilul; indirect câștigă din efectele secundare",
      "Direct e plătit; indirect nu",
      "Sunt sinonime"
    ],
    correct: 1,
    cat: "Planificare",
    explain: "Beneficiari direcți = cei pentru care e proiectul. Indirecți = comunitatea, parteneri, alte grupuri afectate pozitiv."
  },
  {
    q: "Estimarea bottom-up presupune:",
    options: [
      "O singură cifră dată de sponsor",
      "Estimarea fiecărui pachet de lucru din WBS, apoi agregarea",
      "Comparația cu un proiect similar",
      "Aplicarea unui coeficient pe bugetul total"
    ],
    correct: 1,
    cat: "Planificare",
    explain: "Bottom-up = estimezi detaliat la nivel de work package, apoi aduni. Cea mai precisă metodă, dar și cea mai costisitoare."
  },
  {
    q: "Baseline-ul proiectului reprezintă:",
    options: [
      "Prima versiune a codului",
      "Versiunea aprobată a planului (scope, schedule, cost) față de care se măsoară progresul",
      "Bugetul minim acceptabil",
      "Lista de stakeholderi"
    ],
    correct: 1,
    cat: "Planificare",
    explain: "Baseline = referința aprobată. Orice abatere de la baseline necesită change request formal."
  },
  {
    q: "Rezerva de contingență e destinată:",
    options: [
      "Profitului PM-ului",
      "Riscurilor cunoscute (known unknowns) identificate în registrul de riscuri",
      "Cheltuielilor de marketing",
      "Bonusurilor echipei"
    ],
    correct: 1,
    cat: "Planificare",
    explain: "Contingency reserve = buget pentru riscuri identificate. Management reserve = buget pentru riscuri necunoscute (unknown unknowns)."
  },

  // ── Control ───────────────────────────────────────────
  {
    q: "Indicele CPI = 0.85 înseamnă:",
    options: [
      "Proiectul e cu 15% sub buget.",
      "Pentru fiecare leu cheltuit, obții doar 85 de bani de valoare. Ești peste buget.",
      "Proiectul e cu 15% în întârziere.",
      "Calitatea e la 85%."
    ],
    correct: 1,
    cat: "Control",
    explain: "CPI = Earned Value / Actual Cost. CPI < 1 înseamnă că plătești mai mult decât producția reală."
  },
  {
    q: "Indicele SPI = 1.15 indică:",
    options: [
      "Proiect peste buget cu 15%",
      "Proiect sub buget cu 15%",
      "Proiect cu 15% înaintea programului",
      "Proiect cu 15% în întârziere"
    ],
    correct: 2,
    cat: "Control",
    explain: "SPI = EV/PV. SPI > 1 înseamnă că ai realizat mai mult decât planificai pentru momentul curent."
  },
  {
    q: "Ce reprezintă Earned Value (EV)?",
    options: [
      "Bugetul total alocat proiectului",
      "Valoarea muncii efectiv realizate, exprimată în bani",
      "Profitul așteptat la finalul proiectului",
      "Costul total cheltuit până acum"
    ],
    correct: 1,
    cat: "Control",
    explain: "EV măsoară progresul real în termeni monetari. Comparativ cu PV (planificat) și AC (cheltuit)."
  },
  {
    q: "CPI = 0.92 înseamnă:",
    options: ["Sub buget cu 8%", "Peste buget cu 8%", "Înaintea programului cu 8%", "Calitate la 92%"],
    correct: 1,
    cat: "Control",
    explain: "CPI = EV/AC. Sub 1 = cheltui mai mult decât valoarea muncii produse. 8 bani lipsesc la fiecare leu."
  },
  {
    q: "Variance at Completion (VAC) se calculează ca:",
    options: [
      "BAC − EAC",
      "EV − AC",
      "PV − EV",
      "AC − PV"
    ],
    correct: 0,
    cat: "Control",
    explain: "VAC = BAC − EAC. Dacă VAC < 0, proiectul va depăși bugetul planificat. BAC = Budget at Completion."
  },
  {
    q: "Un change request trebuie:",
    options: [
      "Implementat imediat de echipă",
      "Evaluat, aprobat/respins printr-un proces formal de change control",
      "Ignorat dacă vine de la client",
      "Discutat doar la final de proiect"
    ],
    correct: 1,
    cat: "Control",
    explain: "Change control = proces formal. Fiecare cerere e documentată, evaluată (impact pe scope/timp/cost) și aprobată/respinsă."
  },

  // ── Finanțare ─────────────────────────────────────────
  {
    q: "În contextul fondurilor europene, „cheltuieli eligibile” înseamnă:",
    options: [
      "Cheltuieli aprobate în baza contractului de finanțare",
      "Cheltuieli sub 1000 EUR",
      "Cheltuieli făcute de manager",
      "Cheltuieli auditate"
    ],
    correct: 0,
    cat: "Finanțare",
    explain: "Eligibile = se încadrează în categoriile definite de contract și ghidul finanțatorului. Restul sunt neeligibile."
  },
  {
    q: "Cofinanțarea proprie într-un proiect cu fonduri europene reprezintă:",
    options: [
      "Partea de buget acoperită de beneficiar din surse proprii",
      "Profitul proiectului",
      "Cheltuielile neeligibile",
      "Taxa de administrare"
    ],
    correct: 0,
    cat: "Finanțare",
    explain: "Cofinanțarea = contribuția beneficiarului. De ex. dacă finanțarea e 90%, cofinanțarea proprie = 10%."
  },
  {
    q: "Cheltuielile indirecte (regie) includ de obicei:",
    options: [
      "Salariile echipei de proiect",
      "Utilități, chirie birou, consumabile administrative",
      "Achiziția de echipamente",
      "Consultanță externă"
    ],
    correct: 1,
    cat: "Finanțare",
    explain: "Indirecte = costuri care nu se pot atribui direct unei activități: chirie, utilități, materiale de birou."
  },
  {
    q: "Într-un buget de proiect cu fonduri europene, dotările (echipamente) reprezintă de obicei:",
    options: [
      "Sub 10% din buget",
      "70-75% din bugetul total",
      "Exact 50%",
      "Nu sunt eligibile"
    ],
    correct: 1,
    cat: "Finanțare",
    explain: "În programele tipice (ex: start-up nation, microîntreprinderi), dotările constituie 70-75% din buget."
  },

  // ── Închidere ─────────────────────────────────────────
  {
    q: "Lessons Learned se documentează:",
    options: [
      "Doar la final de proiect",
      "La sfârșitul fiecărei faze + la închidere",
      "Doar dacă proiectul a eșuat",
      "Niciodată — sunt informale"
    ],
    correct: 1,
    cat: "Închidere",
    explain: "Lessons learned se captează pe parcurs (la sfârșit de fază) și se sintetizează la închidere."
  },
  {
    q: "Cea mai bună practică pentru predarea proiectului către operațiuni e:",
    options: [
      "Email cu documente",
      "Predare formală cu manual + training echipă + perioadă de overlap",
      "Ședință de 30 minute",
      "Nu există predare formală"
    ],
    correct: 1,
    cat: "Închidere",
    explain: "Predarea ideală: documentație completă, training, perioadă de overlap. Reduce support post-handover."
  },
  {
    q: "La închiderea proiectului, PM-ul trebuie să:",
    options: [
      "Doar să trimită factura finală",
      "Să obțină acceptanța formală a livrabilelor, să arhiveze documentația și să elibereze resursele",
      "Să plece în vacanță",
      "Să înceapă imediat alt proiect"
    ],
    correct: 1,
    cat: "Închidere",
    explain: "Închiderea include: acceptanță formală, lessons learned, arhivare documente, eliberare resurse, raport final."
  },
  {
    q: "Acceptanța formală a livrabilelor se face de către:",
    options: [
      "PM-ul proiectului",
      "Echipa tehnică",
      "Clientul sau sponsorul (conform criteriilor din contract)",
      "Departamentul juridic"
    ],
    correct: 2,
    cat: "Închidere",
    explain: "Acceptanța formală = clientul/sponsorul confirmă că livrabilele îndeplinesc criteriile agreate."
  }
];

// ── Random selection with session persistence ─────────
const QUIZ_SIZE = 15;
const QUIZ_SESSION_KEY = "pm_m1_quiz_selection";

function getQuizSelection() {
  const stored = sessionStorage.getItem(QUIZ_SESSION_KEY);
  if (stored) {
    try {
      const indices = JSON.parse(stored);
      if (Array.isArray(indices) && indices.length === QUIZ_SIZE && indices.every(i => i < QUIZ_BANK.length)) {
        return indices;
      }
    } catch (e) { /* regenerate */ }
  }
  // Fisher-Yates shuffle to pick QUIZ_SIZE unique indices
  const all = Array.from({ length: QUIZ_BANK.length }, (_, i) => i);
  for (let i = all.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [all[i], all[j]] = [all[j], all[i]];
  }
  const selection = all.slice(0, QUIZ_SIZE);
  sessionStorage.setItem(QUIZ_SESSION_KEY, JSON.stringify(selection));
  return selection;
}

// Keep QUIZ_QUESTIONS for backward compatibility (used by M4 gamification)
const QUIZ_QUESTIONS = QUIZ_BANK;

function QuizSection({ state, update, go }) {
  const [quizIndices] = React.useState(() => getQuizSelection());
  const questions = quizIndices.map(i => QUIZ_BANK[i]);

  const [answers, setAnswers] = React.useState({});
  const [submitted, setSubmitted] = React.useState(false);
  const [reviewMode, setReviewMode] = React.useState(false);
  // Timestamp when user opened the quiz — used for `quiz_attempts.started_at`
  const [startedAt] = React.useState(() => new Date().toISOString());

  const select = (qIdx, optIdx) => {
    if (submitted) return;
    setAnswers(prev => ({ ...prev, [qIdx]: optIdx }));
  };

  const submit = () => {
    const correct = questions.filter((q, i) => answers[i] === q.correct).length;
    const score = Math.round((correct / questions.length) * 100);
    setSubmitted(true);
    setReviewMode(true);
    update(s => ({ ...s, m1: { ...s.m1, quizScore: score, quizAttempts: (s.m1.quizAttempts || 0) + 1 }}));

    // Persist the attempt to Supabase (no-op if anonymous / queues if offline).
    // Snapshot just enough question data to reconstruct what was shown — keeps
    // the row useful even if the question bank changes later.
    if (window.Storage?.recordQuizAttempt) {
      const questionSet = questions.map((q, i) => ({
        idx: i,
        bankIdx: quizIndices[i],
        q: q.q,
        cat: q.cat,
        correct: q.correct
      }));
      const answersArray = questions.map((_, i) => ({
        idx: i,
        chosen: answers[i] ?? null,
        correct: answers[i] === questions[i].correct
      }));
      window.Storage.recordQuizAttempt({
        module: "m1",
        questionSet,
        answers: answersArray,
        score,
        startedAt,
        finishedAt: new Date().toISOString()
      }).catch(() => {}); // best-effort
    }
  };

  const reset = () => {
    setAnswers({});
    setSubmitted(false);
    setReviewMode(false);
    // Generate new random selection on retry
    sessionStorage.removeItem(QUIZ_SESSION_KEY);
    window.location.reload();
  };

  const correct = questions.filter((q, i) => answers[i] === q.correct).length;
  const score = submitted ? Math.round((correct / questions.length) * 100) : 0;
  const passed = score >= 60;
  const answered = Object.keys(answers).length;

  // Category stats for results
  const catStats = React.useMemo(() => {
    if (!submitted) return {};
    const stats = {};
    questions.forEach((q, i) => {
      if (!stats[q.cat]) stats[q.cat] = { total: 0, correct: 0 };
      stats[q.cat].total++;
      if (answers[i] === q.correct) stats[q.cat].correct++;
    });
    return stats;
  }, [submitted, answers, questions]);

  return (
    <div>
      <div className="main-head">
        <div className="crumb">Quiz · Modul 1</div>
        <h1 className="section-title">Quiz de fixare — Modul 1</h1>
        <p className="section-lede">
          {QUIZ_SIZE} întrebări alese aleatoriu dintr-o bancă de {QUIZ_BANK.length}. Treci cu minim <strong>60%</strong>. La fiecare încercare primești întrebări diferite.
        </p>
        <div className="section-meta">
          <span><Pill kind="info">{QUIZ_SIZE} din {QUIZ_BANK.length} întrebări</Pill></span>
          <span className="dot"></span>
          <span>Trecere: 60% · Încercări precedente: {state.m1.quizAttempts || 0}</span>
        </div>
      </div>

      {submitted && (
        <div className={`quiz-result ${passed ? "pass" : "fail"}`}>
          <div className="quiz-result-num">{score}%</div>
          <div className="quiz-result-text">
            <div className="quiz-result-title">{passed ? "Felicitări! Ai trecut quiz-ul Modul 1." : "Mai studiază lecțiile și încearcă din nou."}</div>
            <div className="quiz-result-sub">{correct} din {questions.length} răspunsuri corecte · {passed ? "Modul 1 marcat ca finalizat." : "Minim 60% pentru trecere."}</div>
          </div>
          <div style={{display: "flex", gap: 8}}>
            <button className="btn ghost" onClick={reset}>↻ Reia (întrebări noi)</button>
            {passed && <button className="btn primary" onClick={() => go("m2-overview")}>Trec la M2 →</button>}
          </div>
        </div>
      )}

      {submitted && Object.keys(catStats).length > 0 && (
        <div style={{marginBottom: 24, padding: "18px 22px", background: "var(--bg-card)", border: "1px solid var(--line)", borderRadius: 12}}>
          <div className="eyebrow" style={{marginBottom: 12}}>Performanță pe categorii</div>
          <div style={{display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(200px, 1fr))", gap: 10}}>
            {Object.entries(catStats).map(([cat, s]) => {
              const pct = Math.round((s.correct / s.total) * 100);
              return (
                <div key={cat} style={{padding: "10px 14px", background: "var(--bg)", borderRadius: 8, border: "1px solid var(--line)"}}>
                  <div style={{display: "flex", justifyContent: "space-between", marginBottom: 6}}>
                    <span style={{fontSize: 13, fontWeight: 600}}>{cat}</span>
                    <span style={{fontSize: 13, color: "var(--muted)"}}>{s.correct}/{s.total}</span>
                  </div>
                  <div className="progress-bar" style={{background: "var(--line)", margin: 0, height: 5}}>
                    <div className="progress-bar-fill" style={{width: `${pct}%`, background: pct >= 60 ? "var(--accent)" : "var(--danger, #e74c3c)"}}></div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}

      {!submitted && (
        <div className="quiz-progress-bar-card">
          <div>
            <div className="eyebrow" style={{marginBottom: 4}}>Răspunse</div>
            <div style={{fontFamily: "var(--display)", fontSize: 18, fontWeight: 600}}>{answered} / {questions.length}</div>
          </div>
          <div style={{flex: 1, margin: "0 24px"}}>
            <div className="progress-bar" style={{background: "var(--line)", margin: 0, height: 6}}>
              <div className="progress-bar-fill" style={{width: `${(answered/questions.length)*100}%`}}></div>
            </div>
          </div>
          <button className="btn primary" disabled={answered < questions.length} onClick={submit}>
            {answered < questions.length ? `Mai ai ${questions.length - answered}` : "Trimite quiz →"}
          </button>
        </div>
      )}

      <div className="quiz-questions">
        {questions.map((q, i) => {
          const chosen = answers[i];
          const isCorrect = chosen === q.correct;
          return (
            <div key={i} className={`quiz-q ${submitted ? (isCorrect ? "q-correct" : "q-incorrect") : ""}`}>
              <div className="quiz-q-head">
                <span className="quiz-q-num">Q{i+1}</span>
                <Pill kind="default">{q.cat}</Pill>
                <span className="quiz-q-text">{q.q}</span>
                {submitted && (
                  <span className={`quiz-q-mark ${isCorrect ? "ok" : "bad"}`}>{isCorrect ? "✓" : "✗"}</span>
                )}
              </div>
              <div className="quiz-options">
                {q.options.map((opt, j) => {
                  const isSelected = chosen === j;
                  const isAnswer = j === q.correct;
                  let cls = "quiz-opt";
                  if (submitted) {
                    if (isAnswer) cls += " correct";
                    else if (isSelected) cls += " incorrect";
                  } else if (isSelected) cls += " selected";
                  return (
                    <button key={j} className={cls} onClick={() => select(i, j)} disabled={submitted}>
                      <span className="quiz-opt-letter">{String.fromCharCode(65 + j)}</span>
                      <span>{opt}</span>
                      {submitted && isAnswer && <span className="quiz-opt-mark">✓</span>}
                    </button>
                  );
                })}
              </div>
              {submitted && (
                <div className="quiz-explain">
                  <strong>De ce:</strong> {q.explain}
                </div>
              )}
            </div>
          );
        })}
      </div>

      {/* Bottom submit panel — mirrors the top one so users at the end of the
          list don't have to scroll back up. */}
      {!submitted && (
        <div className="quiz-progress-bar-card quiz-progress-bottom">
          <div>
            <div className="eyebrow" style={{marginBottom: 4}}>Răspunse</div>
            <div style={{fontFamily: "var(--display)", fontSize: 18, fontWeight: 600}}>{answered} / {questions.length}</div>
          </div>
          <div style={{flex: 1, margin: "0 24px"}}>
            <div className="progress-bar" style={{background: "var(--line)", margin: 0, height: 6}}>
              <div className="progress-bar-fill" style={{width: `${(answered/questions.length)*100}%`}}></div>
            </div>
          </div>
          <button className="btn primary" disabled={answered < questions.length} onClick={submit}>
            {answered < questions.length ? `Mai ai ${questions.length - answered}` : "Trimite quiz →"}
          </button>
        </div>
      )}

      <div className="foot-actions">
        <button className="btn ghost" onClick={() => go("m1-glossary")}>← Glosar</button>
        {submitted && passed
          ? <button className="btn primary" onClick={() => go("m2-overview")}>Trec la Modul 2 →</button>
          : <button className="btn ghost" onClick={() => go("m1-overview")}>Înapoi la M1</button>
        }
      </div>
    </div>
  );
}

Object.assign(window, { QuizSection, QUIZ_QUESTIONS, QUIZ_BANK });
