/* global React, ReactDOM, CVDocument, emptyData, validateStep, blank, applyLimits,
   StepIdentity, StepSkills, StepStrengths, StepLanguages, StepCourses,
   StepEducation, StepExperience, StepProjects, Head, MAX */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

const STORAGE_KEY = "sn_cv_record_v1";
const STEP_KEY = "sn_cv_step_v1";

// ---- Backend mode -------------------------------------------------------
// false  → prototipo: guarda en localStorage, PDF por impresión del navegador.
// true   → Cloudflare: Save crea/actualiza vía /api/candidates (acceso ABIERTO),
//          carga /api/settings (límites), y devuelve un enlace de edición.
const USE_BACKEND = true;
const API_BASE = ""; // mismo origen al desplegar

// Enlace de retorno/edición: ?cv=<id>&t=<token>. Si no viene, es un CV nuevo.
const AUTH = (() => {
  const p = new URLSearchParams(location.search);
  return { id: p.get("cv"), token: p.get("t") };
})();

const STEPS = [
  { id: "identity", label: "Candidate", comp: StepIdentity },
  { id: "skills", label: "Skills", comp: StepSkills },
  { id: "strengths", label: "Strengths", comp: StepStrengths },
  { id: "languages", label: "Languages", comp: StepLanguages },
  { id: "courses", label: "Courses", comp: StepCourses },
  { id: "education", label: "Education", comp: StepEducation },
  { id: "experience", label: "Experience", comp: StepExperience },
  { id: "projects", label: "Projects", comp: StepProjects },
  { id: "review", label: "Review & Export", comp: null },
];

function loadData() {
  try {
    const raw = localStorage.getItem(STORAGE_KEY);
    if (raw) {
      const parsed = JSON.parse(raw);
      return { ...emptyData(), ...parsed, candidate: { ...emptyData().candidate, ...(parsed.candidate || {}) } };
    }
  } catch (e) { /* ignore */ }
  return emptyData();
}

// ---------- Review & Export ----------
function ReturnLink({ url }) {
  const [copied, setCopied] = useState(false);
  return (
    <div style={{ marginTop: 16, padding: "14px 16px", background: "rgba(174,204,87,.18)", border: "1px solid var(--sn-green)", borderRadius: 10 }}>
      <div style={{ fontWeight: 800, color: "var(--sn-blue)", fontSize: 14, marginBottom: 4 }}>✓ ¡Tu CV fue guardado!</div>
      <div style={{ fontSize: 12.5, color: "var(--sn-ink-70)", lineHeight: 1.5, marginBottom: 10 }}>
        Guarda este enlace para volver y editar tu CV cuando quieras. <b>Es tu acceso personal — no lo compartas.</b>
      </div>
      <div style={{ display: "flex", gap: 8 }}>
        <input readOnly value={url} onClick={(e) => e.target.select()}
          style={{ flex: 1, fontFamily: "ui-monospace, monospace", fontSize: 11.5, border: "1px solid var(--sn-gray-cool)", borderRadius: 6, padding: "9px 11px", background: "#fff", color: "var(--sn-ink)" }} />
        <button type="button" className="btn btn-blue" style={{ padding: "9px 16px", fontSize: 13 }}
          onClick={() => { navigator.clipboard.writeText(url); setCopied(true); setTimeout(() => setCopied(false), 1500); }}>
          {copied ? "¡Copiado!" : "Copiar"}
        </button>
      </div>
    </div>
  );
}

function StepReview({ d, saved, onSave, onPrint }) {
  const counts = [
    ["Technical skills", d.technicalKnowledge.filter(s => s.skillName).length, MAX.technicalKnowledge],
    ["Strengths", d.strengths.filter(s => s.name).length, MAX.strengths],
    ["Languages", d.languages.filter(l => l.language).length, MAX.languages],
    ["Courses / certifications", d.courses.filter(c => c.name).length, MAX.courses],
    ["Education", d.education.filter(e => e.degree || e.university).length, MAX.education],
    ["Professional experience", d.experience.filter(e => e.company || e.jobTitle).length, MAX.experience],
    ["Key projects", d.projects.filter(p => p.title).length, MAX.projects],
  ];
  return (
    <div>
      <Head eyebrow="Step 9 · Review & Export" title="Review & generate CV"
        sub="Check the live preview on the right. Save to store the record, then download the branded PDF." />
      <div style={{ display: "flex", flexDirection: "column", gap: 8, marginBottom: 22 }}>
        {counts.map(([k, n, m]) => (
          <div key={k} style={{ display: "flex", justifyContent: "space-between", fontSize: 13, padding: "8px 12px", background: "var(--sn-offwhite)", borderRadius: 6 }}>
            <span style={{ fontWeight: 600 }}>{k}</span>
            <span style={{ fontWeight: 800, color: "var(--sn-blue)" }}>{n} / {m}</span>
          </div>
        ))}
      </div>

      <button type="button" className="btn btn-primary" style={{ width: "100%", marginBottom: 12 }} onClick={onSave}>
        {saved ? "✓ Guardado — guardar cambios" : "Guardar mi CV"}
      </button>
      <button type="button" className="btn btn-blue" style={{ width: "100%" }} onClick={onPrint}>
        Descargar CV en PDF
      </button>

      {saved && saved.editUrl ? <ReturnLink url={saved.editUrl} /> : saved ? (
        <div style={{ marginTop: 16, padding: "12px 14px", background: "rgba(174,204,87,.18)", border: "1px solid var(--sn-green)", borderRadius: 8, fontSize: 13 }}>
          <b>CV guardado.</b> Guardado localmente como <code>{saved.id}</code>.
        </div>
      ) : null}

      <div className="field-hint" style={{ marginTop: 16 }}>
        Consejo: en el diálogo de impresión, pon márgenes en “Ninguno” y activa “Gráficos de fondo” para un PDF idéntico.
      </div>
    </div>
  );
}

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "formLayout": "guided",
  "density": "comfortable",
  "ctaColor": "green",
  "photoShape": "square"
}/*EDITMODE-END*/;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [data, setData] = useState(loadData);
  const [step, setStep] = useState(() => {
    const s = Number(localStorage.getItem(STEP_KEY));
    return Number.isFinite(s) && s >= 0 && s < STEPS.length ? s : 0;
  });
  const [touched, setTouched] = useState({});  // {stepId: true}
  const [saved, setSaved] = useState(null);     // {id, at, token, editUrl}
  const [booted, setBooted] = useState(!USE_BACKEND);
  const [, bumpLimits] = useState(0);
  const previewRef = useRef(null);
  const scalerRef = useRef(null);

  // Backend: carga límites configurables y, si hay enlace de edición, el registro.
  useEffect(() => {
    if (!USE_BACKEND) return;
    (async () => {
      try {
        const res = await fetch(`${API_BASE}/api/settings`);
        if (res.ok) { applyLimits(await res.json()); bumpLimits(v => v + 1); }
      } catch (e) { /* defaults */ }

      if (AUTH.id && AUTH.token) {
        try {
          const res = await fetch(`${API_BASE}/api/candidates/${AUTH.id}?t=${encodeURIComponent(AUTH.token)}`,
            { headers: { "Authorization": "Bearer " + AUTH.token } });
          if (res.ok) {
            const rec = await res.json();
            const base = emptyData();
            setData({
              ...base,
              candidate: { ...base.candidate, ...rec.candidate, photo: rec.candidate.photoUrl || null },
              technicalKnowledge: rec.technicalKnowledge?.length ? rec.technicalKnowledge : base.technicalKnowledge,
              strengths: rec.strengths?.length ? rec.strengths : base.strengths,
              languages: rec.languages?.length ? rec.languages : base.languages,
              courses: rec.courses?.length ? rec.courses : base.courses,
              education: rec.education?.length ? rec.education : base.education,
              experience: rec.experience?.length ? rec.experience : base.experience,
              projects: rec.projects?.length ? rec.projects : base.projects,
            });
            const editUrl = `${location.origin}/CV%20Builder.html?cv=${AUTH.id}&t=${encodeURIComponent(AUTH.token)}`;
            setSaved({ id: AUTH.id, at: 0, token: AUTH.token, editUrl });
          }
        } catch (e) { /* sigue con datos locales/vacíos */ }
      }
      setBooted(true);
    })();
  }, []);

  // persist
  useEffect(() => { try { localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); } catch (e) {} }, [data]);
  useEffect(() => { localStorage.setItem(STEP_KEY, String(step)); }, [step]);

  // handlers
  const h = useMemo(() => ({
    setCandidate: (field, val) => setData(d => ({ ...d, candidate: { ...d.candidate, [field]: val } })),
    setItem: (section, i, field, val) => setData(d => {
      const arr = d[section].slice(); arr[i] = { ...arr[i], [field]: val }; return { ...d, [section]: arr };
    }),
    addItem: (section) => setData(d => {
      const factory = { technicalKnowledge: blank.skill, strengths: blank.strength, languages: blank.language,
        courses: blank.course, education: blank.education, experience: blank.experience, projects: blank.project }[section];
      if (d[section].length >= MAX[section]) return d;
      return { ...d, [section]: [...d[section], factory()] };
    }),
    removeItem: (section, i) => setData(d => ({ ...d, [section]: d[section].filter((_, j) => j !== i) })),
  }), []);

  const cur = STEPS[step];
  const errors = useMemo(() => validateStep(cur.id, data), [cur.id, data]);
  const showErrors = touched[cur.id] ? errors : {};

  // per-step status for chips
  const stepStatus = (s, i) => {
    if (i === step) return "active";
    if (touched[s.id] && Object.keys(validateStep(s.id, data)).length) return "error";
    if (i < step) return "done";
    return "";
  };

  function goNext() {
    const e = validateStep(cur.id, data);
    setTouched(t => ({ ...t, [cur.id]: true }));
    if (Object.keys(e).length) {
      document.querySelector(".form-body").scrollTo({ top: 0, behavior: "smooth" });
      return;
    }
    setStep(s => Math.min(STEPS.length - 1, s + 1));
    document.querySelector(".form-body").scrollTo({ top: 0 });
  }
  function goPrev() { setStep(s => Math.max(0, s - 1)); document.querySelector(".form-body").scrollTo({ top: 0 }); }
  function goTo(i) { setTouched(t => ({ ...t, [cur.id]: true })); setStep(i); }

  async function save() {
    if (USE_BACKEND) {
      try {
        const editToken = saved?.token || AUTH.token || null;
        const res = await fetch(`${API_BASE}/api/candidates`, {
          method: "POST", headers: { "Content-Type": "application/json" },
          body: JSON.stringify({ ...data, token: editToken }),
        });
        const out = await res.json();
        if (!res.ok) { alert("No se pudo guardar:\n" + (out.details || [out.error]).join("\n")); return; }
        setSaved({ id: out.id, at: Date.now(), token: out.token, editUrl: out.editUrl });
        // refleja el enlace en la URL para que un refresh siga en modo edición
        try { history.replaceState(null, "", `?cv=${out.id}&t=${encodeURIComponent(out.token)}`); } catch (e) {}
      } catch (e) { alert("Error de red al guardar."); }
      return;
    }
    const id = saved?.id || "CV-" + Math.random().toString(36).slice(2, 8).toUpperCase();
    const demoUrl = `${location.origin}${location.pathname}?cv=${id}&t=demo`;
    setSaved({ id, at: Date.now(), token: "demo", editUrl: demoUrl });
    try { localStorage.setItem(STORAGE_KEY, JSON.stringify(data)); } catch (e) {}
  }
  function printCV() {
    if (USE_BACKEND && saved?.id) {
      const tok = saved.token ? `&t=${encodeURIComponent(saved.token)}` : "";
      window.open(`${API_BASE}/api/candidates/${saved.id}/pdf?photoShape=${t.photoShape}${tok}`, "_blank");
      return;
    }
    window.print();
  }

  // fit-to-width preview scaling (uses CSS zoom)
  useEffect(() => {
    function fit() {
      const pane = previewRef.current, sc = scalerRef.current;
      if (!pane || !sc) return;
      const avail = pane.clientWidth - 56;
      const z = Math.max(0.32, Math.min(1, avail / 720));
      sc.style.zoom = z;
    }
    fit();
    const ro = new ResizeObserver(fit);
    if (previewRef.current) ro.observe(previewRef.current);
    return () => ro.disconnect();
  }, []);

  // apply photo-shape tweak to CV doc
  useEffect(() => {
    const r = { square: "6px", rounded: "22px", circle: "50%" }[t.photoShape] || "6px";
    document.documentElement.style.setProperty("--cv-photo-radius", r);
  }, [t.photoShape]);

  const StepComp = cur.comp;
  const progress = ((step) / (STEPS.length - 1)) * 100;
  const appClass = [
    "app",
    (t.formLayout === "focus" && cur.id !== "review") ? "layout-focus" : "",
    t.density === "compact" ? "density-compact" : "",
    t.ctaColor === "blue" ? "cta-blue" : "",
  ].join(" ");

  if (USE_BACKEND && !booted) {
    return (
      <div style={{ height: "100vh", display: "grid", placeItems: "center", background: "var(--sn-offwhite)" }}>
        <div style={{ textAlign: "center" }}>
          <img src="assets/logo-color.png" alt="Scale Nearshoring" style={{ height: 36, marginBottom: 18, opacity: .9 }} />
          <div style={{ width: 24, height: 24, margin: "0 auto", border: "3px solid var(--sn-gray-cool)", borderTopColor: "var(--sn-blue)", borderRadius: "50%", animation: "sp .7s linear infinite" }} />
          <style>{"@keyframes sp{to{transform:rotate(360deg)}}"}</style>
        </div>
      </div>
    );
  }

  return (
    <div className={appClass}>
      <div className="pane-form">
        <div className="form-top">
          <div className="brandbar">
            <img src="assets/logo-color.png" alt="Scale Nearshoring" />
            <span className="tagline">Candidate CV Builder</span>
          </div>
          <div className="steps">
            {STEPS.map((s, i) => (
              <button key={s.id} className={"step-chip " + stepStatus(s, i)} onClick={() => goTo(i)}>
                <span className="num">{stepStatus(s, i) === "done" ? "✓" : i + 1}</span>{s.label}
              </button>
            ))}
          </div>
          <div className="progress-track"><div className="progress-fill" style={{ width: progress + "%" }} /></div>
          <div style={{ height: 14 }} />
        </div>

        <div className="form-body">
          {cur.id === "review"
            ? <StepReview d={data} saved={saved} onSave={save} onPrint={printCV} />
            : <StepComp d={data} errors={showErrors} h={h} />}
        </div>

        <div className="form-nav">
          <button className="btn btn-ghost" onClick={goPrev} disabled={step === 0}>← Back</button>
          <div className="flex-grow" />
          {step < STEPS.length - 1
            ? <button className="btn btn-primary" onClick={goNext}>Continue →</button>
            : <button className="btn btn-blue" onClick={printCV}>Download PDF</button>}
        </div>
      </div>

      <div className="pane-preview" ref={previewRef}>
        <div className="cv-toolbar">
          <div>
            <div className="ttl">Live CV preview</div>
            <div className="meta">Scale Nearshoring · 2 pages · updates as you type</div>
          </div>
          <div className="acts">
            <button className="btn btn-ghost" style={{ padding: "9px 16px", fontSize: 13 }} onClick={save}>Save</button>
            <button className="btn btn-blue" style={{ padding: "9px 16px", fontSize: 13 }} onClick={printCV}>Download PDF</button>
          </div>
        </div>
        <div className="cv-scaler" ref={scalerRef}>
          <CVDocument data={data} />
        </div>
      </div>

      <TweaksPanel title="Tweaks">
        <TweakSection label="Form experience" />
        <TweakRadio label="Layout" value={t.formLayout}
          options={["guided", "focus"]} onChange={(v) => setTweak("formLayout", v)} />
        <TweakRadio label="Density" value={t.density}
          options={["comfortable", "compact"]} onChange={(v) => setTweak("density", v)} />
        <TweakRadio label="Primary button" value={t.ctaColor}
          options={["green", "blue"]} onChange={(v) => setTweak("ctaColor", v)} />
        <TweakSection label="CV document" />
        <TweakRadio label="Photo shape" value={t.photoShape}
          options={["square", "rounded", "circle"]} onChange={(v) => setTweak("photoShape", v)} />
      </TweaksPanel>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
