/* global React, Icon, Button, cx, fmtLabel, VIDEOS, VIDEO_BY_ID, CAT, LEARNER, US_STATES, CLE_LOG, STATE_CLE_REQUIREMENTS, STATE_NAME_BY_CODE, STATE_FILING_FEE, todayLabel */
// LPE Learning Center — CLE Center: reporting cycle, attendance log,
// certificate (with verification code), and retroactive-credit application.

const { useState: useStateCle, useMemo: useMemoCle } = React;

// deterministic 4-char code from a seed
function verifyCode(seed) {
  let h = 0;
  for (let i = 0; i < seed.length; i++) h = (h * 31 + seed.charCodeAt(i)) >>> 0;
  const chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789";
  let out = "";
  for (let i = 0; i < 4; i++) { out += chars[h % chars.length]; h = Math.floor(h / chars.length) + 7; }
  return out;
}
function fullVerifyCode(v, entry, learner) {
  const yr = new Date(entry.attendedOn).getFullYear() || 2026;
  const codeNum = v.code.replace("LPE-", "");
  return `LPE-${yr}-${codeNum}-${learner.initials}-${verifyCode(v.id + entry.attendedOn)}`;
}

function CircularProgress({ percent, label, value, target, colorClass = "" }) {
  const radius = 40;
  const stroke = 6;
  const normalizedRadius = radius - stroke;
  const circumference = normalizedRadius * 2 * Math.PI;
  const strokeDashoffset = circumference - (Math.min(100, percent) / 100) * circumference;

  return (
    <div className="circular-progress-card" style={{
      display: "flex",
      alignItems: "center",
      gap: "16px",
      background: "var(--cream-2, #FAF8F5)",
      border: "1px solid var(--grey-200, #EAE5DF)",
      padding: "16px 20px",
      borderRadius: "12px",
      flex: "1 1 200px",
      minWidth: "220px",
      boxShadow: "0 2px 6px rgba(0,0,0,0.015)"
    }}>
      <div style={{ position: "relative", width: radius * 2, height: radius * 2, flexShrink: 0 }}>
        <svg height={radius * 2} width={radius * 2}>
          <circle
            stroke="var(--grey-200, #EAE5DF)"
            fill="transparent"
            strokeWidth={stroke}
            r={normalizedRadius}
            cx={radius}
            cy={radius}
          />
          <circle
            stroke={colorClass === "teal" ? "var(--teal)" : "var(--orange)"}
            fill="transparent"
            strokeWidth={stroke}
            strokeDasharray={circumference + ' ' + circumference}
            style={{ strokeDashoffset, transition: "stroke-dashoffset 0.5s ease-out", transform: "rotate(-90deg)", transformOrigin: "50% 50%" }}
            r={normalizedRadius}
            cx={radius}
            cy={radius}
            strokeLinecap="round"
          />
        </svg>
        <div style={{
          position: "absolute",
          top: "50%",
          left: "50%",
          transform: "translate(-50%, -50%)",
          fontWeight: "bold",
          fontSize: "14px",
          color: "var(--navy)"
        }}>
          {Math.round(percent)}%
        </div>
      </div>
      <div>
        <span style={{ fontSize: "11px", fontWeight: "600", textTransform: "uppercase", letterSpacing: "0.06em", color: "var(--grey)", display: "block", marginBottom: "2px" }}>{label}</span>
        <span style={{ fontSize: "18px", fontWeight: "bold", color: "var(--navy)" }}>{value.toFixed(1)} <span style={{ fontSize: "12px", fontWeight: "normal", color: "var(--grey)" }}>/ {target.toFixed(1)} hours</span></span>
      </div>
    </div>
  );
}

// ---- Reporting cycle tracker ----
function ReportingTracker({ learner, updateLearner, generalEarned, ethicsEarned }) {
  const req = STATE_CLE_REQUIREMENTS[learner.targetState] || STATE_CLE_REQUIREMENTS["Ohio"];
  const totalEarned = generalEarned + ethicsEarned;
  const genReq = req.totalHours;
  const ethReq = req.ethicsHours;
  const genPct = Math.min(100, (totalEarned / genReq) * 100);
  const ethPct = Math.min(100, (ethicsEarned / ethReq) * 100);

  const endRaw = learner.reportingPeriod ? learner.reportingPeriod.end : "2027-12-31";
  const end = new Date(endRaw);
  const validEnd = isNaN(end.getTime()) ? new Date("2027-12-31") : end;
  const monthsLeft = Math.max(1, Math.round((validEnd.getTime() - Date.now()) / (86400000 * 30)));
  const daysLeft = Math.max(0, Math.round((validEnd.getTime() - Date.now()) / 86400000));
  const remaining = Math.max(0, genReq - totalEarned);
  const perMonth = (remaining / monthsLeft).toFixed(1);
  const onTrack = remaining === 0;

  return (
    <div className="rp-track" style={{ marginBottom: "28px" }}>
      <div className="rp-head" style={{ marginBottom: "20px" }}>
        <div>
          <h3 style={{ fontSize: "20px", fontWeight: "bold", color: "var(--navy)", marginBottom: "4px" }}>{learner.targetState} CLE Cycle</h3>
          <div style={{ display: "flex", alignItems: "center", gap: "8px", fontSize: "12px", color: "var(--grey)" }}>
            <Icon name="calendar" size={13} />
            <span>Filing deadline: <b>{learner.reportingPeriod ? learner.reportingPeriod.end : "Dec 31, 2027"}</b> ({daysLeft} days remaining)</span>
          </div>
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 14, flexWrap: "wrap" }}>
          <span className="rp-cycle">{learner.reportingPeriod ? `${learner.reportingPeriod.start} – ${learner.reportingPeriod.end}` : "Jan 1, 2026 – Dec 31, 2027"} · {req.cycleYears}-year cycle</span>
          <select className="select-styled" value={learner.targetState} onChange={(e) => updateLearner({ targetState: e.target.value, barState: e.target.value })}>
            {Object.keys(STATE_CLE_REQUIREMENTS).map((s) => <option key={s}>{s}</option>)}
          </select>
        </div>
      </div>
      
      <div className="rp-gauges-container" style={{ display: "flex", gap: "16px", flexWrap: "wrap", marginBottom: "20px" }}>
        <CircularProgress percent={genPct} label="Total CLE Hours" value={totalEarned} target={genReq} />
        <CircularProgress percent={ethPct} label="Ethics Hours" value={ethicsEarned} target={ethReq} colorClass="teal" />
      </div>

      {onTrack ? (
        <div className="rp-warn ok"><Icon name="checkCircle" size={15} style={{ color: "var(--teal)" }} /> <span>You've met the {req.totalHours}-hour requirement for this cycle. Keep any extra hours on record.</span></div>
      ) : (
        <div className="rp-warn"><Icon name="info" size={15} style={{ color: "var(--gold)" }} /> <span>{remaining.toFixed(1)} hours remaining with about {monthsLeft} months left — roughly <b>{perMonth} hrs/month</b> to hit your cycle target{ethicsEarned < ethReq ? `, including ${(ethReq - ethicsEarned).toFixed(1)} more ethics hours` : ""}.</span></div>
      )}
    </div>
  );
}

function CertificateModal({ entry, learner, onClose, onToast, onPrint }) {
  if (!entry) return null;
  const v = VIDEO_BY_ID[entry.videoId] || { title: "Course", sub: "", cle: { credits: 0, type: "General" }, code: entry.videoId, duration: 60 };
  const code = fullVerifyCode(v, entry, learner);
  
  const isCle = v.cle && v.cle.eligible;
  const creditsVal = isCle ? v.cle.credits : (v.duration >= 60 ? v.duration / 60 : 1.0);
  const creditsLabel = isCle ? `${v.cle.type} credit hours` : "Instruction hours";
  
  return (
    <div className="modal-scrim" onClick={onClose}>
      <div className="modal" style={{ maxWidth: 620 }} onClick={(e) => e.stopPropagation()}>
        <div className="m-head">
          <h3>Certificate of completion</h3>
          <button className="x" onClick={onClose}><Icon name="x" size={18} /></button>
        </div>
        <div className="m-body">
          <div className="cert">
            <div className="c-wm">The Law Practice Exchange</div>
            <div className="c-h">This certifies that</div>
            <div className="c-name">{learner.name}</div>
            <div className="c-h">has completed the {isCle ? "continuing legal education" : "professional development"} program</div>
            <div className="c-title">{v.title} — {v.sub}</div>
            <div className="c-grid">
              <div><div className="v">{creditsVal.toFixed(1)}</div><div className="l">{creditsLabel}</div></div>
              <div><div className="v">{entry.attendedOn}</div><div className="l">Date attended</div></div>
              <div><div className="v">{v.code}</div><div className="l">Program ID</div></div>
            </div>
            <div className="c-sign">
              <div>
                <div className="sig">Tom Lenfestey</div>
                <div className="sig-l">Founder, LPE · Program sponsor</div>
              </div>
              <div style={{ textAlign: "right" }}>
                <div className="sig" style={{ paddingRight: 0 }}>{entry.live ? "Live" : "On-demand"}</div>
                <div className="sig-l">Attendance type</div>
              </div>
            </div>
            <div style={{ marginTop: 18, paddingTop: 14, borderTop: "1px solid var(--grey-200)", display: "flex", justifyContent: "space-between", alignItems: "center", flexWrap: "wrap", gap: 8 }}>
              <span style={{ fontFamily: "var(--font-mono)", fontSize: 11, letterSpacing: "0.06em", color: "var(--navy)" }}>Verification: {code}</span>
              <span className="small" style={{ fontSize: 11 }}>Verify at lawpracticeexchange.com/verify</span>
            </div>
          </div>
        </div>
        <div className="m-foot">
          <Button variant="ghost" onClick={onClose}>Close</Button>
          <Button variant="primary" icon="download" onClick={() => { if (onPrint) onPrint({ type: "cert", entry, learner }); else onToast("Certificate downloaded (PDF)"); onClose(); }}>Download PDF</Button>
        </div>
      </div>
    </div>
  );
}

function AffidavitPreview({ v, form, learner, onClose, onPrint }) {
  return (
    <div className="modal-scrim" onClick={onClose}>
      <div className="modal" style={{ maxWidth: 600 }} onClick={(e) => e.stopPropagation()}>
        <div className="m-head"><h3>Completion affidavit — preview</h3><button className="x" onClick={onClose}><Icon name="x" size={18} /></button></div>
        <div className="m-body">
          <div className="cert" style={{ borderColor: "var(--grey-300)" }}>
            <div className="c-wm" style={{ fontSize: 18 }}>The Law Practice Exchange</div>
            <div className="c-h" style={{ marginTop: 18 }}>Affidavit of attendance · {form.state} Bar</div>
            <p style={{ fontSize: 13, lineHeight: 1.7, color: "var(--navy)", marginTop: 14 }}>
              I, <b>{learner.name}</b> (Bar No. <b>{form.bar || "—"}</b>), affirm that I attended the continuing legal education program
              <b> “{v.title}”</b> ({v.code}) sponsored by The Law Practice Exchange on <b>{form.attended}</b>, comprising
              <b> {v.cle.credits.toFixed(1)} hour{v.cle.credits === 1 ? "" : "s"}</b> of {v.cle.type.toLowerCase()} instruction, and request that the credit be applied to my {form.state} reporting period.
            </p>
            <div className="c-sign" style={{ marginTop: 20 }}>
              <div><div className="sig">{learner.name}</div><div className="sig-l">Affiant signature</div></div>
              <div style={{ textAlign: "right" }}><div className="sig" style={{ paddingRight: 0 }}>{todayLabel()}</div><div className="sig-l">Date</div></div>
            </div>
          </div>
        </div>
        <div className="m-foot">
          <Button variant="ghost" onClick={onClose}>Close</Button>
          <Button variant="primary" icon="download" onClick={() => { if (onPrint) onPrint({ type: "affidavit", video: v, form, learner }); onClose(); }}>Download affidavit (PDF)</Button>
        </div>
      </div>
    </div>
  );
}

function RetroForm({ learner, onToast, videos = window.VIDEOS, videoMap = window.VIDEO_BY_ID, setCleRequests, onPrint, attendedSet = new Set() }) {
  const eligible = videos.filter((v) => v.cle.eligible && !attendedSet.has(v.id));
  
  if (eligible.length === 0) {
    return (
      <div className="form-card" style={{ textAlign: "center", padding: "30px 20px" }}>
        <Icon name="checkCircle" size={32} style={{ color: "var(--teal)", marginBottom: 12 }} />
        <h4 style={{ color: "var(--navy)", fontWeight: "bold", marginBottom: 6 }}>All Credits Logged</h4>
        <p style={{ fontSize: 13, color: "var(--grey)", margin: 0 }}>You have already completed all available CLE sessions in our library. Your certificates are ready to download in the log.</p>
      </div>
    );
  }

  const [submitted, setSubmitted] = useStateCle(false);
  const [showPreview, setShowPreview] = useStateCle(false);
  const [form, setForm] = useStateCle({ state: learner.targetState, bar: learner.barNo, session: eligible[0] ? eligible[0].id : "", attended: "2026-05-14", email: learner.email });
  const v = videoMap[form.session] || eligible[0];
  const stateCode = v && (STATE_CLE_REQUIREMENTS[form.state] || {}).code;
  const preAccredited = v && stateCode && v.cle.accredited && v.cle.accredited.includes(stateCode);
  const fee = STATE_FILING_FEE[form.state];

  function set(k, val) { setForm((f) => ({ ...f, [k]: val })); }

  if (submitted) {
    return (
      <div className="form-card">
        <div className="form-success">
          <span className="ic"><Icon name="checkCircle" size={20} /></span>
          <div>
            <b>Application submitted.</b> We've packaged your attendance record for <b>{v.title}</b> ({v.cle.credits.toFixed(1)} {v.cle.type.toLowerCase()} hours) and emailed a completion affidavit to {form.email}. Submit it to the {form.state} bar to apply the credit retroactively.
            <div style={{ marginTop: 14 }}><Button variant="secondary" size="sm" icon="rotate" onClick={() => setSubmitted(false)}>Submit another</Button></div>
          </div>
        </div>
      </div>
    );
  }

  return (
    <form className="form-card" onSubmit={(e) => {
      e.preventDefault();
      if (typeof setCleRequests === "function") {
        let isDuplicate = false;
        setCleRequests((prev) => {
          if ((prev || []).some(r => r.videoId === form.session && r.status !== 'rejected')) {
            isDuplicate = true;
            return prev;
          }
          return [
            {
              id: "req-" + Date.now(),
              learnerName: learner.name,
              learnerEmail: learner.email,
              videoId: form.session,
              state: form.state,
              barNo: form.bar,
              attendedOn: form.attended || todayLabel(),
              credits: v ? v.cle.credits : 1.0,
              type: v ? v.cle.type : "General",
              status: "pending",
              timestamp: "Just now",
            },
            ...prev,
          ];
        });
        if (isDuplicate) {
          onToast("A credit application for this session has already been submitted.");
          return;
        }
      }
      setSubmitted(true);
      onToast("Retroactive credit application submitted");
    }}>
      <p className="form-note">
        Many state bars allow you to claim CLE credit for a program after the fact. Pick the session you attended and the state where you need the hours — we'll generate the attendance affidavit that bar requires.
      </p>
      <div className="form-field">
        <label>Session attended</label>
        <select value={form.session} onChange={(e) => set("session", e.target.value)}>
          {eligible.map((vv) => <option key={vv.id} value={vv.id}>{vv.code} · {vv.title} ({vv.cle.credits.toFixed(1)} {vv.cle.type})</option>)}
        </select>
      </div>
      <div className="form-2col">
        <div className="form-field">
          <label>Bar jurisdiction</label>
          <select value={form.state} onChange={(e) => set("state", e.target.value)}>
            {US_STATES.map((s) => <option key={s} value={s}>{s}</option>)}
          </select>
        </div>
        <div className="form-field">
          <label>Bar number</label>
          <input type="text" value={form.bar} onChange={(e) => set("bar", e.target.value)} placeholder="e.g. OH-0094213" />
        </div>
      </div>

      {v && preAccredited ? (
        <div className="form-success" style={{ marginBottom: 16 }}>
          <span className="ic"><Icon name="checkCircle" size={18} /></span>
          <div>Good news — LPE is <b>directly accredited in {form.state}</b>. You don't need a retroactive application; hours for this session are logged to your record automatically once you mark it attended.</div>
        </div>
      ) : v ? (
        <>
          <div className="form-2col">
            <div className="form-field">
              <label>Date attended</label>
              <input type="date" value={form.attended} onChange={(e) => set("attended", e.target.value)} />
            </div>
            <div className="form-field">
              <label>Email for affidavit</label>
              <input type="email" value={form.email} onChange={(e) => set("email", e.target.value)} />
            </div>
          </div>
          <p className="form-note" style={{ marginTop: 0 }}>
            Credit hours: <b style={{ color: "var(--navy)" }}>{v.cle.credits.toFixed(1)} {v.cle.type.toLowerCase()}</b>.
            {fee && fee !== "$0" ? <> The {form.state} bar charges a {fee} affidavit filing fee. LPE does not.</> : <> No filing fee applies in {form.state}.</>}
          </p>
          <div style={{ display: "flex", gap: 10 }}>
            <Button variant="ghost" type="button" icon="eye" onClick={() => setShowPreview(true)}>Preview affidavit</Button>
            <Button variant="primary" type="submit" icon="send" style={{ flex: 1 }}>Submit application</Button>
          </div>
        </>
      ) : null}

      {showPreview ? <AffidavitPreview v={v} form={form} learner={learner} onClose={() => setShowPreview(false)} onPrint={onPrint} /> : null}
    </form>
  );
}

function CleScreen({ attendedSet, verifyMap, learner, updateLearner, onToast, onOpen, videos = window.VIDEOS, videoMap = window.VIDEO_BY_ID, setCleRequests, onPrint }) {
  const [certFor, setCertFor] = useStateCle(null);

  const log = useMemoCle(() => {
    const rows = [];
    (attendedSet || new Set()).forEach((id) => {
      if (videoMap[id]) {
        rows.push({ id: "attended-" + id, videoId: id, attendedOn: todayLabel(), live: false, certificate: true });
      }
    });
    return rows;
  }, [attendedSet, videoMap]);

  const totalCredits = log.reduce((s, e) => s + (videoMap[e.videoId] ? videoMap[e.videoId].cle.credits : 0), 0);
  const ethicsCredits = log.reduce((s, e) => s + (videoMap[e.videoId] && videoMap[e.videoId].cle.type === "Ethics" ? videoMap[e.videoId].cle.credits : 0), 0);
  const generalCredits = totalCredits - ethicsCredits;

  return (
    <div className="lc-page">
      <div className="cle-hero">
        <div>
          <div className="ch-eyebrow"><span className="pip" />CLE Center</div>
          <h1>Your continuing education record</h1>
          <p className="ch-sub">Every eligible session you attend is logged here. Download certificates, or apply for retroactive credit in any participating jurisdiction.</p>
        </div>
        <div className="ch-figs">
          <div className="f"><div className="v">{totalCredits.toFixed(1)}</div><div className="l">Credit hours</div></div>
          <div className="f"><div className="v">{ethicsCredits.toFixed(1)}</div><div className="l">Ethics hours</div></div>
          <div className="f"><div className="v">{log.length}</div><div className="l">Certificates</div></div>
        </div>
      </div>

      <ReportingTracker learner={learner} updateLearner={updateLearner} generalEarned={generalCredits} ethicsEarned={ethicsCredits} />

      <div className="cle-cols">
        <div>
          <div className="lc-section-head" style={{ marginTop: 0 }}>
            <h2>Attendance log</h2>
            <span className="meta">{learner.name} · {learner.targetState} bar {learner.barNo}</span>
          </div>
          {log.length ? (
            <table className="data-table">
              <thead>
                <tr>
                  <th>Program</th>
                  <th>Attended</th>
                  <th>Type</th>
                  <th>Verification</th>
                  <th className="num">Hours</th>
                  <th className="num">Certificate</th>
                </tr>
              </thead>
              <tbody>
                {log.map((e) => {
                  const v = videoMap[e.videoId];
                  if (!v) return null;
                  const vr = verifyMap[e.videoId];
                  const isCle = v.cle && v.cle.eligible;
                  const creditsVal = isCle ? v.cle.credits : (v.duration >= 60 ? v.duration / 60 : 1.0);
                  const typeLabel = isCle ? v.cle.type : "Professional";
                  return (
                    <tr key={e.id}>
                      <td>
                        <div className="t-title name-link" onClick={() => onOpen(e.videoId)}>{v.title}</div>
                        <div className="t-code">{v.code} · {e.live ? "Attended live" : "On-demand"}</div>
                      </td>
                      <td>{e.attendedOn}</td>
                      <td><span className={cx("pill", typeLabel === "Ethics" ? "ethics" : typeLabel === "Professional" ? "default" : "general")}>{typeLabel}</span></td>
                      <td>
                        {e.live ? <span className="small">Live roster</span>
                          : vr && vr.total ? <span className="small">{vr.confirmed} of {vr.total} confirmed{vr.missed ? ` · ${vr.missed} missed` : ""}</span>
                          : <span className="small" style={{ color: "var(--teal-600)" }}>Verified</span>}
                      </td>
                      <td className="num">{creditsVal.toFixed(1)}</td>
                      <td className="num"><a className="link" onClick={() => setCertFor(e)}><Icon name="certificate" size={13} /> View</a></td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          ) : (
            <div className="empty"><Icon name="award" size={28} /><h4>No CLE hours logged yet</h4><p>Watch an eligible session and mark it attended — it'll appear here with a downloadable certificate.</p></div>
          )}

          <div style={{ marginTop: 16, display: "flex", alignItems: "center", gap: 10, padding: "14px 16px", background: "var(--cream-2)", border: "1px solid var(--grey-200)", fontSize: 12.5, color: "var(--grey)" }}>
            <Icon name="info" size={16} style={{ color: "var(--navy)", flexShrink: 0 }} />
            <span>LPE programs are sponsor-accredited in participating states. For jurisdictions where we are not directly accredited, use the retroactive application — most bars accept a completion affidavit.</span>
          </div>
        </div>

        <div>
          <div className="lc-section-head" style={{ marginTop: 0 }}><h2>Apply for retroactive credit</h2></div>
          <RetroForm learner={learner} onToast={onToast} videos={videos} videoMap={videoMap} setCleRequests={setCleRequests} onPrint={onPrint} attendedSet={attendedSet} />
        </div>
      </div>

      <CertificateModal entry={certFor} learner={learner} onClose={() => setCertFor(null)} onToast={onToast} onPrint={onPrint} />
    </div>
  );
}

Object.assign(window, { CleScreen, CertificateModal, RetroForm, ReportingTracker });
