/* =========================================================
   Dr. Boechat — Shared form components (React, Babel)
   Exposes components on window for the three form apps.
   ========================================================= */
const { useState, useRef, useEffect, useCallback } = React;

/* ---------------- Masks ---------------- */
const onlyDigits = (s) => (s || "").replace(/\D/g, "");
const maskCPF = (v) => {
  const d = onlyDigits(v).slice(0, 11);
  return d
    .replace(/(\d{3})(\d)/, "$1.$2")
    .replace(/(\d{3})(\d)/, "$1.$2")
    .replace(/(\d{3})(\d{1,2})$/, "$1-$2");
};
const maskPhone = (v) => {
  const d = onlyDigits(v).slice(0, 11);
  if (d.length <= 10)
    return d.replace(/(\d{2})(\d)/, "($1) $2").replace(/(\d{4})(\d)/, "$1-$2");
  return d.replace(/(\d{2})(\d)/, "($1) $2").replace(/(\d{5})(\d)/, "$1-$2");
};
const maskCEP = (v) => onlyDigits(v).slice(0, 8).replace(/(\d{5})(\d)/, "$1-$2");
const maskDate = (v) => {
  const d = onlyDigits(v).slice(0, 8);
  return d.replace(/(\d{2})(\d)/, "$1/$2").replace(/(\d{2})(\d)/, "$1/$2");
};
const MASKS = { cpf: maskCPF, phone: maskPhone, cep: maskCEP, date: maskDate };

/* ---------------- Validators ---------------- */
const isCPFComplete = (v) => onlyDigits(v).length === 11;
const isEmail = (v) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(v.trim());
const isPhoneComplete = (v) => onlyDigits(v).length >= 10;
const isDateComplete = (v) => onlyDigits(v).length === 8;

/* ---------------- Icons ---------------- */
const Ico = {
  back: <path d="M15 18l-6-6 6-6" />,
  alert: <g><path d="M12 8v5" /><path d="M12 16h.01" /><circle cx="12" cy="12" r="10" /></g>,
  arrowR: <g><path d="M5 12h14" /><path d="M13 6l6 6-6 6" /></g>,
  arrowL: <g><path d="M19 12H5" /><path d="M11 18l-6-6 6-6" /></g>,
  check: <path d="M20 6L9 17l-5-5" />,
  send: <g><path d="M22 2L11 13" /><path d="M22 2l-7 20-4-9-9-4 20-7z" /></g>,
  eraser: <g><path d="M20 20H7L3 16a2 2 0 0 1 0-3l9-9 7 7-8 8" /></g>,
};
const Svg = ({ d, w = 18, sw = 1.8, fill = "none" }) => (
  <svg viewBox="0 0 24 24" width={w} height={w} fill={fill} stroke="currentColor"
    strokeWidth={sw} strokeLinecap="round" strokeLinejoin="round">{d}</svg>
);

/* ---------------- AppTop ---------------- */
function AppTop({ logo = "../assets/logo-purple.png" }) {
  return (
    <div className="app-top">
      <img src={logo} alt="Dr. Boechat" />
      <a className="back" href="../index.html"><Svg d={Ico.back} w={16} /> Início</a>
    </div>
  );
}

/* ---------------- Field wrapper ---------------- */
function Field({ label, required, error, hint, full, children }) {
  return (
    <div className={"field" + (full ? " col-2" : "") + (error ? " is-error" : "")}>
      {label && (
        <label>{label}{required && <span className="req">*</span>}</label>
      )}
      {children}
      {error ? (
        <span className="msg err"><Svg d={Ico.alert} w={14} sw={2} /> {error}</span>
      ) : hint ? (
        <span className="msg">{hint}</span>
      ) : null}
    </div>
  );
}

/* ---------------- TextField (with optional mask) ---------------- */
function TextField({
  label, value, onChange, mask, type = "text", required, error, hint,
  placeholder, full, inputMode, maxLength,
}) {
  const filled = value && String(value).length > 0 && !error;
  const handle = (e) => {
    let v = e.target.value;
    if (mask && MASKS[mask]) v = MASKS[mask](v);
    onChange(v);
  };
  return (
    <div className={"field" + (full ? " col-2" : "") + (error ? " is-error" : "") + (filled ? " is-filled" : "")}>
      {label && <label>{label}{required && <span className="req">*</span>}</label>}
      <input
        type={type} value={value || ""} onChange={handle} placeholder={placeholder}
        inputMode={inputMode || (mask === "cpf" || mask === "cep" || mask === "phone" || mask === "date" ? "numeric" : undefined)}
        maxLength={maxLength}
      />
      {error ? (
        <span className="msg err"><Svg d={Ico.alert} w={14} sw={2} /> {error}</span>
      ) : hint ? (<span className="msg">{hint}</span>) : null}
    </div>
  );
}

/* ---------------- SelectField ---------------- */
function SelectField({ label, value, onChange, options, required, error, hint, full, placeholder = "Selecione…" }) {
  const filled = value && value.length > 0 && !error;
  return (
    <div className={"field" + (full ? " col-2" : "") + (error ? " is-error" : "") + (filled ? " is-filled" : "")}>
      {label && <label>{label}{required && <span className="req">*</span>}</label>}
      <select value={value || ""} onChange={(e) => onChange(e.target.value)}>
        <option value="" disabled>{placeholder}</option>
        {options.map((o) => <option key={o} value={o}>{o}</option>)}
      </select>
      {error ? (
        <span className="msg err"><Svg d={Ico.alert} w={14} sw={2} /> {error}</span>
      ) : hint ? (<span className="msg">{hint}</span>) : null}
    </div>
  );
}

/* ---------------- TextArea ---------------- */
function TextArea({ label, value, onChange, required, error, hint, placeholder, rows }) {
  const filled = value && value.length > 0;
  return (
    <div className={"field col-2" + (error ? " is-error" : "") + (filled ? " is-filled" : "")}>
      {label && <label>{label}{required && <span className="req">*</span>}</label>}
      <textarea value={value || ""} onChange={(e) => onChange(e.target.value)}
        placeholder={placeholder} rows={rows} />
      {error ? (
        <span className="msg err"><Svg d={Ico.alert} w={14} sw={2} /> {error}</span>
      ) : hint ? (<span className="msg">{hint}</span>) : null}
    </div>
  );
}

/* ---------------- ChoiceGroup (radio/checkbox chips) ---------------- */
function ChoiceGroup({ options, value, onChange, multi }) {
  const isOn = (o) => multi ? (value || []).includes(o) : value === o;
  const toggle = (o) => {
    if (multi) {
      const set = new Set(value || []);
      set.has(o) ? set.delete(o) : set.add(o);
      onChange([...set]);
    } else onChange(o);
  };
  return (
    <div className="choices">
      {options.map((o) => (
        <label key={o} className={"choice" + (multi ? " checkbox" : "") + (isOn(o) ? " checked" : "")}>
          <input type={multi ? "checkbox" : "radio"} checked={isOn(o)} onChange={() => toggle(o)} />
          <span className="dot" />{o}
        </label>
      ))}
    </div>
  );
}

/* ---------------- Yes/No row (anamnese) ---------------- */
function YesNo({ q, value, onChange }) {
  return (
    <div className="tnf">
      <span className="q">{q}</span>
      <div className="seg2">
        <button className={value === "sim" ? "on-yes" : ""} onClick={() => onChange("sim")}>Sim</button>
        <button className={value === "nao" ? "on-no" : ""} onClick={() => onChange("nao")}>Não</button>
      </div>
    </div>
  );
}

/* ---------------- Stepper ---------------- */
function Stepper({ steps, current }) {
  const pct = ((current) / (steps.length - 1)) * 100;
  return (
    <div className="stepper">
      <div className="bar"><i style={{ width: pct + "%" }} /></div>
      <div className="steps">
        {steps.map((s, i) => (
          <div key={s} className={"st" + (i === current ? " active" : i < current ? " done" : "")}>
            <span className="ix">{i < current ? <Svg d={Ico.check} w={12} sw={2.5} /> : i + 1}</span>
            <span className="lbl">{s}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

/* ---------------- Section head ---------------- */
function SectionHead({ num, title }) {
  return (
    <div className="f-section-head">
      {num && <span className="num">{num}</span>}
      <h2>{title}</h2>
    </div>
  );
}

/* ---------------- Signature pad ---------------- */
function SignaturePad({ onChange }) {
  const ref = useRef(null);
  const [signed, setSigned] = useState(false);
  const drawing = useRef(false);
  const last = useRef(null);

  const setup = useCallback(() => {
    const c = ref.current; if (!c) return;
    const r = c.getBoundingClientRect();
    const dpr = window.devicePixelRatio || 1;
    c.width = r.width * dpr; c.height = r.height * dpr;
    const ctx = c.getContext("2d");
    ctx.scale(dpr, dpr);
    ctx.lineWidth = 2.2; ctx.lineCap = "round"; ctx.lineJoin = "round";
    ctx.strokeStyle = "#3F0C63";
  }, []);

  useEffect(() => { setup(); window.addEventListener("resize", setup); return () => window.removeEventListener("resize", setup); }, [setup]);

  const pos = (e) => {
    const c = ref.current; const r = c.getBoundingClientRect();
    const t = e.touches ? e.touches[0] : e;
    return { x: t.clientX - r.left, y: t.clientY - r.top };
  };
  const start = (e) => { e.preventDefault(); drawing.current = true; last.current = pos(e); };
  const move = (e) => {
    if (!drawing.current) return; e.preventDefault();
    const ctx = ref.current.getContext("2d");
    const p = pos(e);
    ctx.beginPath(); ctx.moveTo(last.current.x, last.current.y); ctx.lineTo(p.x, p.y); ctx.stroke();
    last.current = p;
    if (!signed) { setSigned(true); onChange && onChange(true); }
  };
  const end = () => { drawing.current = false; };
  const clear = () => {
    const c = ref.current; const ctx = c.getContext("2d");
    ctx.clearRect(0, 0, c.width, c.height);
    setSigned(false); onChange && onChange(false);
  };

  return (
    <div className="sig-pad-wrap">
      <canvas ref={ref} className={"sig-pad" + (signed ? " signed" : "")}
        onMouseDown={start} onMouseMove={move} onMouseUp={end} onMouseLeave={end}
        onTouchStart={start} onTouchMove={move} onTouchEnd={end} />
      <div className="sig-tools">
        <span className="hint">{signed ? "Assinatura registrada." : "Assine no quadro acima com o dedo ou mouse."}</span>
        <button className="btn-ghost" onClick={clear}><Svg d={Ico.eraser} w={16} /> Limpar</button>
      </div>
    </div>
  );
}

/* ---------------- Scale row (0–N selectable) ---------------- */
function ScaleRow({ value, onChange, min = 0, max = 10, leftLabel, rightLabel }) {
  const items = [];
  for (let i = min; i <= max; i++) items.push(i);
  return (
    <div className="scale-row">
      <div className="scale-btns">
        {items.map((i) => (
          <button key={i} type="button" className={"scale-btn" + (value === i ? " sel" : "")}
            onClick={() => onChange(i)}>{i}</button>
        ))}
      </div>
      {(leftLabel || rightLabel) && (
        <div className="scale-anchors"><span>{leftLabel}</span><span>{rightLabel}</span></div>
      )}
    </div>
  );
}

/* ---------------- Question block (number + text + control) ---------------- */
function QBlock({ num, text, children }) {
  return (
    <div className="q-block">
      <div className="q-head">
        {num != null && <span className="q-num">{num}</span>}
        <span className="q-text">{text}</span>
      </div>
      {children}
    </div>
  );
}

/* ---------------- Legend (key for scale points) ---------------- */
function ScaleLegend({ items }) {
  return (
    <div className="scale-legend">
      {items.map((it) => (
        <span key={it.v}><b>{it.v}</b>&nbsp;{it.l}</span>
      ))}
    </div>
  );
}

/* ---------------- Result panel (score + band) ---------------- */
function ResultPanel({ score, max, band, bandColor, caption, children }) {
  return (
    <div className="result" style={bandColor ? { background: bandColor } : null}>
      <div className="result-score">{score}<span className="result-max">/{max}</span></div>
      {band && <div className="result-band">{band}</div>}
      {caption && <p className="result-cap">{caption}</p>}
      {children}
    </div>
  );
}

/* ---------------- Sticky progress (answered / total) ---------------- */
function AnsweredBar({ answered, total }) {
  const pct = total ? Math.round((answered / total) * 100) : 0;
  return (
    <div className="answered-bar">
      <div className="ab-track"><i style={{ width: pct + "%" }} /></div>
      <span className="ab-label">{answered} de {total} respondidas</span>
    </div>
  );
}

/* ---------------- Success screen ---------------- */
function DoneScreen({ title, children }) {
  return (
    <div className="done-screen">
      <div className="check"><Svg d={Ico.check} w={36} sw={2.4} /></div>
      <h2>{title}</h2>
      <p>{children}</p>
      <div className="tagline">Atende pessoas, não doenças.</div>
    </div>
  );
}

Object.assign(window, {
  onlyDigits, MASKS, isCPFComplete, isEmail, isPhoneComplete, isDateComplete,
  Ico, Svg, AppTop, Field, TextField, SelectField, TextArea, ChoiceGroup,
  YesNo, Stepper, SectionHead, SignaturePad, DoneScreen,
  ScaleRow, QBlock, ScaleLegend, ResultPanel, AnsweredBar,
});
