/* Portal O-Lab — módulo compartido (paleta, iconos y átomos de UI).
   Todo se expone en window.PORTAL_UI para que los otros scripts text/babel
   lo consuman sin depender del scope global de Babel. */
(function () {
  const C = {
    ink: "#17131F",
    orange: "#FF6600",
    orangeDk: "#C24E00",
    pink: "#FF3D7F",
    amber: "#FFB347",
    lime: "#C6F24E",
    violet: "#6C4CF1",
    violetDk: "#4A2FBF",
    cyan: "#12C2E9",
    cyanDk: "#0B7C93",
    green: "#0E8F5B",
    greenBg: "#E3FBF0",
    greenBd: "#A9EBCB",
    cream: "#FBF8F4",
    sand: "#F5F2EE",
    sand2: "#F0EAE2",
    line: "#EDE6DD",
    line2: "#E1DAD1",
    mut: "#8B8194",
    mut2: "#7A6F84",
    mut3: "#5C5468",
    mut4: "#B0A7BB",
    orangeSoft: "#FFF1E4",
    orangeSoftBd: "#FFC79A",
    violetSoft: "#F4F0FF",
    violetSoftBd: "#D9CDFF",
    cyanSoft: "#EAF9FE",
    darkGrad: "linear-gradient(160deg,#17131F,#2B1B4D)",
    heroGrad: "linear-gradient(160deg,#17131F,#3A1E00)",
    feedBg:
      "radial-gradient(1100px 700px at 15% 0%, #2B1B4D 0%, transparent 60%), radial-gradient(900px 600px at 90% 20%, #4A1F00 0%, transparent 55%), #17131F",
  };

  const FONT = "'Plus Jakarta Sans', system-ui, sans-serif";

  // --- Iconos SVG (stroke=currentColor salvo que se pase fill) ---
  function Icon(props) {
    const { name, size = 20, color = "currentColor", fill = "none", sw = 1.9 } = props;
    const P = { width: size, height: size, viewBox: "0 0 24 24", fill };
    const s = { stroke: color, strokeWidth: sw, strokeLinecap: "round", strokeLinejoin: "round" };
    const paths = {
      home: <path d="M4 11l8-7 8 7v9H4v-9z" {...s} />,
      briefcase: <path d="M3 8h18v11H3zM9 8V5h6v3" {...s} />,
      flask: <path d="M9 3h6M10 3v6l-4 8a3 3 0 003 4h6a3 3 0 003-4l-4-8V3" {...s} />,
      trophy: <path d="M7 4h10v5a5 5 0 01-10 0V4zM12 14v4m-3 3h6" {...s} />,
      user: (
        <g>
          <circle cx="12" cy="8" r="3.4" {...s} />
          <path d="M5 20c1.5-3.6 4-5 7-5s5.5 1.4 7 5" {...s} />
        </g>
      ),
      calendar: <path d="M5 4h14v16H5zM5 9h14M9 3v3M15 3v3" {...s} />,
      test: (
        <g>
          <path d="M5 4h14v16H5z" {...s} />
          <path d="M8 10l2 2 4-4" stroke={C.lime} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" />
          <path d="M8 16h8" {...s} />
        </g>
      ),
      chat: <path d="M4 6h16v10H9l-5 4V6z" {...s} />,
      heart: <path d="M12 20s-7-4.6-7-9.3A4 4 0 0112 8a4 4 0 017 2.7C19 15.4 12 20 12 20z" {...s} />,
      external: <path d="M7 17L17 7M9 7h8v8" {...s} />,
      star: <path d="M12 4l2.4 5 5.6.8-4 4 1 5.6L12 16.9 6.9 19.4l1-5.6-4-4L9.6 9z" fill={color} stroke="none" />,
      coin: (
        <g>
          <circle cx="12" cy="12" r="9" fill={color} stroke="none" />
          <path d="M12 7v10M9 10h5a2 2 0 010 4H9" stroke="#fff" strokeWidth="1.6" strokeLinecap="round" />
        </g>
      ),
      fire: <path d="M12 2c1 4-3 5-3 8a3 3 0 006 0c0-1-.5-2-1-3 3 2 5 4.5 5 8a7 7 0 11-14 0C5 9 12 8 12 2z" fill={color} stroke="none" />,
      clock: (
        <g>
          <circle cx="12" cy="12" r="9" {...s} />
          <path d="M12 8v4l3 2" {...s} />
        </g>
      ),
      filter: <path d="M4 6h16M7 12h10M10 18h4" {...s} />,
      search: (
        <g>
          <circle cx="11" cy="11" r="7" {...s} />
          <path d="M20 20l-3.5-3.5" {...s} />
        </g>
      ),
      check: <path d="M5 12l4 4L19 7" {...s} sw={2.4} />,
      close: <path d="M6 6l12 12M18 6L6 18" {...s} />,
      logout: <path d="M15 4h4v16h-4M11 8l-4 4 4 4M7 12h9" {...s} />,
      mail: <path d="M4 6h16v12H4zM4 7l8 6 8-6" {...s} />,
      whatsapp: <path d="M12 3a9 9 0 00-7.7 13.6L3 21l4.6-1.2A9 9 0 1012 3z" {...s} />,
      phone: <path d="M5 4h4l2 5-3 2a12 12 0 005 5l2-3 5 2v4a2 2 0 01-2 2A16 16 0 013 6a2 2 0 012-2z" {...s} />,
      plus: <path d="M12 5v14M5 12h14" {...s} sw={2.2} />,
    };
    return (
      <svg {...P} xmlns="http://www.w3.org/2000/svg">
        {paths[name] || null}
      </svg>
    );
  }

  function initials(name) {
    return String(name || "?")
      .split(" ")
      .filter(Boolean)
      .slice(0, 2)
      .map((w) => w[0])
      .join("")
      .toUpperCase();
  }

  // --- Átomos ---
  function Avatar({ name, initials: ini, bg, color = "#fff", size = 38, radius = "999px", style }) {
    return (
      <div
        style={{
          width: size, height: size, borderRadius: radius, flexShrink: 0,
          background: bg || "linear-gradient(135deg,#FF6600,#FF3D7F)",
          display: "flex", alignItems: "center", justifyContent: "center",
          fontSize: size * 0.32, fontWeight: 800, color, ...style,
        }}
      >
        {ini || initials(name)}
      </div>
    );
  }

  function Bar({ pct, color = C.orange, track = C.sand2, h = 7, shine }) {
    const bg = shine
      ? "linear-gradient(90deg,#FF6600,#FFB347,#C6F24E)"
      : color;
    return (
      <div style={{ height: h, borderRadius: 999, background: track, overflow: "hidden" }}>
        <div style={{ width: pct, height: "100%", borderRadius: 999, background: bg, backgroundSize: shine ? "200% 100%" : undefined, animation: shine ? "olabShine 3s linear infinite" : undefined }} />
      </div>
    );
  }

  function Pill({ children, color, bg, bd, style }) {
    return (
      <span style={{ fontSize: 11, fontWeight: 800, color, background: bg, border: bd ? `1px solid ${bd}` : undefined, padding: "5px 10px", borderRadius: 999, whiteSpace: "nowrap", ...style }}>
        {children}
      </span>
    );
  }

  function Btn({ children, onClick, kind = "primary", style, type }) {
    const base = { border: 0, fontFamily: FONT, fontWeight: 800, cursor: "pointer", borderRadius: 14, padding: "11px 14px", fontSize: 13 };
    const kinds = {
      primary: { background: C.orange, color: "#fff" },
      dark: { background: C.ink, color: "#fff" },
      ghost: { background: "#fff", color: C.ink, border: `1px solid ${C.line2}` },
      lime: { background: C.lime, color: C.ink },
      soft: { background: C.orangeSoft, color: C.orangeDk, border: `1px solid ${C.orangeSoftBd}` },
    };
    return (
      <button type={type || "button"} onClick={onClick} style={{ ...base, ...kinds[kind], ...style }}>
        {children}
      </button>
    );
  }

  function Card({ children, style, onClick }) {
    return (
      <div onClick={onClick} style={{ background: "#fff", border: `1px solid ${C.line}`, borderRadius: 22, ...style }}>
        {children}
      </div>
    );
  }

  // Match ring (conic gradient donut con % al centro)
  function MatchRing({ pct, size = 56 }) {
    const turn = (parseInt(pct, 10) || 0) / 100;
    return (
      <div style={{ width: size, height: size, borderRadius: 999, flexShrink: 0, background: `conic-gradient(${C.lime} 0turn ${turn}turn, #E6E1F5 ${turn}turn 1turn)`, display: "flex", alignItems: "center", justifyContent: "center" }}>
        <div style={{ width: size - 12, height: size - 12, borderRadius: 999, background: "#fff", display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center" }}>
          <span style={{ fontSize: size * 0.25, fontWeight: 800, color: C.ink, lineHeight: 1 }}>{pct}</span>
          <span style={{ fontSize: 7, fontWeight: 800, color: C.mut, letterSpacing: "0.06em" }}>MATCH</span>
        </div>
      </div>
    );
  }

  // Calcula un match % entre el perfil del candidato y una vacante, cruzando
  // los roles que busca + sus competencias con el texto de la vacante.
  function words(s) { return String(s || "").toLowerCase().normalize("NFD").replace(/[̀-ͯ]/g, "").split(/[^a-z0-9]+/).filter((w) => w.length > 3); }
  function computeMatch(profile, vac) {
    profile = profile || {};
    const text = words([vac.cargo, vac.title, vac.requisitos, vac.gap, vac.area, vac.perfil, vac.company, vac.empresa].join(" ")).join(" ");
    const has = (s) => words(s).some((w) => text.includes(w));
    let score = 42;
    (profile.desiredRoles || []).forEach((r) => { if (has(r)) score += 13; });
    (profile.skills || []).forEach((s) => { if (has(s.name)) score += Math.round((parseInt(s.pct, 10) || 0) / 10); });
    if (profile.profession && has(profile.profession)) score += 8;
    if (profile.role && has(profile.role)) score += 6;
    return Math.max(38, Math.min(99, Math.round(score)));
  }
  function matchColor(n) { return n >= 88 ? "#0E8F5B" : n >= 78 ? "#FF6600" : n >= 65 ? "#6C4CF1" : "#8B8194"; }

  function useIsMobile(bp) {
    bp = bp || 640;
    const [m, setM] = React.useState(typeof window !== "undefined" && window.innerWidth < bp);
    React.useEffect(() => {
      const on = () => setM(window.innerWidth < bp);
      on();
      window.addEventListener("resize", on);
      return () => window.removeEventListener("resize", on);
    }, [bp]);
    return m;
  }

  window.PORTAL_UI = { C, FONT, Icon, Avatar, Bar, Pill, Btn, Card, MatchRing, initials, computeMatch, matchColor, useIsMobile };
})();
