// === Module 1 - Lesson 1.2 - PERT Diagram with Critical Path ===

function calculatePERT(activities) {
  const map = {};
  activities.forEach(a => { map[a.id] = { ...a, ES: 0, EF: 0, LS: 0, LF: 0, slack: 0, depth: 0 }; });

  // Topological sort + compute depth (longest path from root)
  const computed = new Set();
  let safety = 100;
  while (computed.size < activities.length && safety-- > 0) {
    activities.forEach(a => {
      if (computed.has(a.id)) return;
      if (a.deps.every(d => computed.has(d))) {
        const node = map[a.id];
        node.ES = a.deps.length ? Math.max(...a.deps.map(d => map[d].EF)) : 0;
        node.EF = node.ES + Number(a.duration || 0);
        node.depth = a.deps.length ? Math.max(...a.deps.map(d => map[d].depth)) + 1 : 0;
        computed.add(a.id);
      }
    });
  }

  // Project duration = max EF
  const projectEnd = Math.max(...Object.values(map).map(n => n.EF));

  // Backward pass — compute LF, LS
  // Reverse topological order
  const inDegrees = {};
  activities.forEach(a => a.deps.forEach(d => { inDegrees[d] = (inDegrees[d] || 0) + 1; }));

  // Initialize LF for ending activities (no successors) = projectEnd
  Object.values(map).forEach(n => {
    if (!inDegrees[n.id]) { n.LF = projectEnd; n.LS = n.LF - Number(n.duration || 0); }
  });

  // Iterate backwards
  let safety2 = 100;
  const lfComputed = new Set(Object.values(map).filter(n => !inDegrees[n.id]).map(n => n.id));
  while (lfComputed.size < activities.length && safety2-- > 0) {
    activities.forEach(a => {
      if (lfComputed.has(a.id)) return;
      // Find successors
      const successors = activities.filter(b => b.deps.includes(a.id));
      if (successors.every(s => lfComputed.has(s.id))) {
        const node = map[a.id];
        node.LF = Math.min(...successors.map(s => map[s.id].LS));
        node.LS = node.LF - Number(a.duration || 0);
        lfComputed.add(a.id);
      }
    });
  }

  // Compute slack and critical path
  Object.values(map).forEach(n => {
    n.slack = n.LS - n.ES;
    n.critical = n.slack === 0;
  });

  return { nodes: map, projectEnd, depths: Math.max(...Object.values(map).map(n => n.depth)) + 1 };
}

function PERTSection({ state, update, go }) {
  const acts = state.m1.pertActivities;
  const { nodes, projectEnd, depths } = React.useMemo(() => calculatePERT(acts), [acts]);

  const updateActivity = (id, patch) => {
    update(s => ({ ...s, m1: { ...s.m1, pertActivities: s.m1.pertActivities.map(a => a.id === id ? { ...a, ...patch } : a) }}));
  };
  const addActivity = () => {
    const nextCode = String.fromCharCode(65 + acts.length); // A, B, C…
    update(s => ({ ...s, m1: { ...s.m1, pertActivities: [...s.m1.pertActivities, {
      id: Date.now(), code: nextCode, name: "Activitate nouă", duration: 3, deps: []
    }] }}));
  };
  const removeActivity = (id) => {
    update(s => ({
      ...s,
      m1: { ...s.m1,
        pertActivities: s.m1.pertActivities
          .filter(a => a.id !== id)
          .map(a => ({ ...a, deps: a.deps.filter(d => d !== id) }))
      }
    }));
  };
  const toggleDep = (activityId, depId) => {
    update(s => ({ ...s, m1: { ...s.m1, pertActivities: s.m1.pertActivities.map(a => {
      if (a.id !== activityId) return a;
      const has = a.deps.includes(depId);
      return { ...a, deps: has ? a.deps.filter(d => d !== depId) : [...a.deps, depId] };
    }) }}));
  };

  // Layout: group nodes by depth, assign y positions
  const byDepth = {};
  acts.forEach(a => {
    const d = nodes[a.id].depth;
    byDepth[d] = byDepth[d] || [];
    byDepth[d].push(a.id);
  });
  const COL_W = 200;
  const ROW_H = 130;
  const NODE_W = 170;
  const NODE_H = 100;
  const PAD_X = 30;
  const PAD_Y = 30;
  const positions = {};
  Object.entries(byDepth).forEach(([depth, ids]) => {
    ids.forEach((id, i) => {
      positions[id] = { x: PAD_X + (+depth) * COL_W, y: PAD_Y + i * ROW_H };
    });
  });
  const totalW = PAD_X * 2 + depths * COL_W;
  const totalH = PAD_Y * 2 + Math.max(...Object.values(byDepth).map(a => a.length)) * ROW_H;

  const criticalCount = Object.values(nodes).filter(n => n.critical).length;

  return (
    <div>
      <div className="main-head">
        <div className="crumb">Lecția 1.2 · Modul 1</div>
        <h1 className="section-title">Diagrama PERT</h1>
        <p className="section-lede">
          Adaugi activități cu durate și dependențe. Sistemul calculează automat <strong>Early Start, Early Finish, Late Start, Late Finish, slack</strong> și <strong>drumul critic</strong>.
        </p>
        <div className="section-meta">
          <span><Pill kind="info">Interactiv</Pill></span>
          <span className="dot"></span>
          <span>{acts.length} activități · drum critic = {criticalCount} pași · durată = {projectEnd} zile</span>
        </div>
      </div>

      <Card title="Rețea activități" sub={`Durată proiect: ${projectEnd} zile`}
        action={<button className="btn small primary" onClick={addActivity}>+ Activitate</button>}>
        <div className="pert-canvas-wrap">
          <svg width={totalW} height={totalH} className="pert-canvas">
            {/* Connection lines */}
            {acts.map(a => a.deps.map(depId => {
              const from = positions[depId];
              const to = positions[a.id];
              if (!from || !to) return null;
              const fromX = from.x + NODE_W;
              const fromY = from.y + NODE_H / 2;
              const toX = to.x;
              const toY = to.y + NODE_H / 2;
              const midX = (fromX + toX) / 2;
              const isCritical = nodes[depId].critical && nodes[a.id].critical;
              return (
                <g key={`${depId}-${a.id}`}>
                  <path
                    d={`M ${fromX} ${fromY} C ${midX} ${fromY}, ${midX} ${toY}, ${toX} ${toY}`}
                    stroke={isCritical ? "#ef4444" : "#cdd1e0"}
                    strokeWidth={isCritical ? 2.5 : 1.5}
                    fill="none"
                    strokeDasharray={isCritical ? "0" : "4 3"}
                  />
                  <circle cx={toX} cy={toY} r={isCritical ? 4 : 3} fill={isCritical ? "#ef4444" : "#9ba0b8"} />
                </g>
              );
            }))}
            {/* Activity nodes */}
            {acts.map(a => {
              const pos = positions[a.id];
              const n = nodes[a.id];
              if (!pos) return null;
              return (
                <g key={a.id} transform={`translate(${pos.x},${pos.y})`}>
                  <rect width={NODE_W} height={NODE_H} rx={10}
                    fill={n.critical ? "#fef2f2" : "#ffffff"}
                    stroke={n.critical ? "#ef4444" : "#d2d7e6"}
                    strokeWidth={n.critical ? 2 : 1} />
                  {/* ES | duration | EF */}
                  <text x={12} y={20} fontSize="10" fontFamily="var(--mono)" fill="#6b7390" fontWeight="500">ES {n.ES}</text>
                  <text x={NODE_W/2} y={20} fontSize="11" fontFamily="var(--mono)" fill="#0a0e1c" textAnchor="middle" fontWeight="700">{a.duration}d</text>
                  <text x={NODE_W - 12} y={20} fontSize="10" fontFamily="var(--mono)" fill="#6b7390" textAnchor="end" fontWeight="500">EF {n.EF}</text>
                  {/* Code + name */}
                  <text x={12} y={44} fontSize="14" fontFamily="var(--display)" fill={n.critical ? "#b91c1c" : "#0a0e1c"} fontWeight="700">{a.code}</text>
                  <text x={32} y={44} fontSize="12" fontFamily="var(--sans)" fill="#0a0e1c" fontWeight="500">{a.name.length > 22 ? a.name.slice(0, 20) + "…" : a.name}</text>
                  {/* LS | slack | LF */}
                  <text x={12} y={68} fontSize="10" fontFamily="var(--mono)" fill="#6b7390" fontWeight="500">LS {n.LS}</text>
                  <text x={NODE_W/2} y={68} fontSize="10" fontFamily="var(--mono)" textAnchor="middle"
                    fill={n.critical ? "#b91c1c" : "#10b981"} fontWeight="600">
                    slack {n.slack}
                  </text>
                  <text x={NODE_W - 12} y={68} fontSize="10" fontFamily="var(--mono)" fill="#6b7390" textAnchor="end" fontWeight="500">LF {n.LF}</text>
                  {n.critical && (
                    <rect x={NODE_W - 14} y={NODE_H - 14} width={6} height={6} fill="#ef4444" rx={1.5} />
                  )}
                </g>
              );
            })}
          </svg>
        </div>

        <div style={{display: "flex", gap: 14, marginTop: 16, fontFamily: "var(--mono)", fontSize: 11, color: "var(--ink-3)", flexWrap: "wrap"}}>
          <span style={{display: "flex", alignItems: "center", gap: 6}}><span style={{width: 14, height: 2, background: "#ef4444"}}></span>Drum critic</span>
          <span style={{display: "flex", alignItems: "center", gap: 6}}><span style={{width: 14, height: 1.5, background: "#9ba0b8", borderTop: "1.5px dashed #9ba0b8"}}></span>Dependență non-critică</span>
          <span style={{display: "flex", alignItems: "center", gap: 6}}><span style={{width: 10, height: 10, background: "#fef2f2", border: "2px solid #ef4444", borderRadius: 2}}></span>Activitate critică (slack=0)</span>
        </div>
      </Card>

      <Card title="Configurare activități"
        sub="EDITEAZĂ DURATA · ADAUGĂ DEPENDENȚE">
        <div className="pert-table">
          <div className="pert-table-head">
            <span>Cod</span>
            <span>Denumire</span>
            <span>Durată</span>
            <span>Dependențe (apasă pentru a marca)</span>
            <span></span>
          </div>
          {acts.map(a => (
            <div key={a.id} className="pert-row">
              <input className="pert-code" value={a.code} onChange={e => updateActivity(a.id, { code: e.target.value.toUpperCase().slice(0,2) })} maxLength={2} />
              <input className="pert-name" value={a.name} onChange={e => updateActivity(a.id, { name: e.target.value })} />
              <input className="pert-dur" type="number" min="1" value={a.duration} onChange={e => updateActivity(a.id, { duration: +e.target.value || 1 })} />
              <div className="pert-deps">
                {acts.filter(x => x.id !== a.id).map(other => {
                  const has = a.deps.includes(other.id);
                  return (
                    <button key={other.id}
                      className={`pert-dep-chip ${has ? "active" : ""}`}
                      onClick={() => toggleDep(a.id, other.id)}
                      title={other.name}>
                      {other.code}
                    </button>
                  );
                })}
                {acts.length === 1 && <span className="muted" style={{fontSize: 12}}>—</span>}
              </div>
              <button className="btn icon" onClick={() => removeActivity(a.id)}>×</button>
            </div>
          ))}
        </div>
      </Card>

      <Card title="Cum se citește diagrama" sub="LECȚIE">
        <div style={{display: "grid", gridTemplateColumns: "1fr 1fr", gap: 24}}>
          <div>
            <h4 style={{fontFamily: "var(--display)", fontSize: 16, fontWeight: 600, margin: "0 0 8px"}}>Calculele automate</h4>
            <ul style={{margin: 0, paddingLeft: 18, fontSize: 13.5, color: "var(--ink-2)", lineHeight: 1.7}}>
              <li><strong>ES (Early Start):</strong> cel mai devreme moment când poți începe activitatea, dacă toate predecesoarele s-au terminat la timp.</li>
              <li><strong>EF (Early Finish):</strong> ES + durată.</li>
              <li><strong>LF (Late Finish):</strong> cel mai târziu moment când poți termina fără să întârzii proiectul.</li>
              <li><strong>LS (Late Start):</strong> LF − durată.</li>
              <li><strong>Slack:</strong> LS − ES = câte zile poți să întârzii activitatea fără să afectezi proiectul.</li>
            </ul>
          </div>
          <div>
            <h4 style={{fontFamily: "var(--display)", fontSize: 16, fontWeight: 600, margin: "0 0 8px"}}>Drumul critic</h4>
            <p style={{margin: "0 0 10px", fontSize: 13.5, color: "var(--ink-2)", lineHeight: 1.55}}>
              Lanțul de activități cu <strong>slack = 0</strong>. Dacă vreuna se întârzie cu o zi, întreg proiectul se întârzie cu o zi.
            </p>
            <p style={{margin: 0, fontSize: 13.5, color: "var(--ink-2)", lineHeight: 1.55}}>
              <strong>Regula PM:</strong> monitorizezi obsesiv drumul critic. Pe celelalte activități ai marjă de manevră.
            </p>
          </div>
        </div>
      </Card>

      <div className="foot-actions">
        <button className="btn ghost" onClick={() => go("m1-definitions")}>← Definiții</button>
        <button className="btn primary" onClick={() => { markM1LessonDone("m1-pert", update); go("m1-eisenhower"); }}>Continuă: Eisenhower →</button>
      </div>
    </div>
  );
}

Object.assign(window, { PERTSection, calculatePERT });
