/* global React */
const { useState, useEffect, useRef } = React;

/* ============================================================
   SKILLS — grouped by category, drag to rearrange
   ============================================================ */
const GROUPS = [
  {
    id: "eng",
    title: "Engineering",
    sub: "Languages, frameworks, runtime models",
    icon: "stack",
    skills: [
      {
        id: "dotnet",
        cat: "Backend · Core",
        name: ".NET / C#",
        detail: "ASP.NET Core 2 → 9, C# 6–13. REST, gRPC, JSON-RPC, WCF. Functional C# with LangExt / OneOf.",
        yrs: "7 yrs",
        lvl: 0.95
      },
      {
        id: "orleans",
        cat: "Architecture",
        name: "Microsoft Orleans",
        detail: "Distributed actor-model systems in production at Metso — grain design, clustering, persistence.",
        yrs: "2 yrs",
        lvl: 0.78
      },
      {
        id: "react",
        cat: "Frontend",
        name: "React 18 + TypeScript",
        detail: "Hooks, Suspense, Tailwind / MUI / Bootstrap. Storybook-driven design systems with strict TS.",
        yrs: "5 yrs",
        lvl: 0.88
      }
    ]
  },
  {
    id: "ops",
    title: "Platform & Operations",
    sub: "Cloud, infra-as-code, observability",
    icon: "cloud",
    skills: [
      {
        id: "azure",
        cat: "Cloud · Infra",
        name: "Azure + Terraform",
        detail: "Migrating VM-era workloads to Azure-native. IaC with Terraform across Azure & AWS, K8s with Helm.",
        yrs: "4 yrs",
        lvl: 0.86
      },
      {
        id: "obs",
        cat: "Observability",
        name: "DataDog · OpenTelemetry",
        detail: "Tracing, metrics, logging from day one. Grafana dashboards, SLO-driven ops, alert hygiene.",
        yrs: "3 yrs",
        lvl: 0.82
      }
    ]
  },
  {
    id: "data",
    title: "Data",
    sub: "Stores, modelling, query design",
    icon: "data",
    skills: [
      {
        id: "data",
        cat: "Databases",
        name: "SQL · Postgres · Mongo",
        detail: "MS SQL, PostgreSQL, MongoDB, Redis. Time-series in InfluxDB / Azure Data Explorer.",
        yrs: "7 yrs",
        lvl: 0.85
      }
    ]
  },
  {
    id: "people",
    title: "Product & Leadership",
    sub: "Backlog, stakeholders, outcomes",
    icon: "target",
    skills: [
      {
        id: "po",
        cat: "Product · Delivery",
        name: "Agile / Scrum (PO)",
        detail: "Backlog ownership, refinement, INVEST stories, release planning. JIRA + Confluence-led.",
        yrs: "3 yrs",
        lvl: 0.86
      },
      {
        id: "stake",
        cat: "Leadership",
        name: "Stakeholder management",
        detail: "Bridge engineering ↔ business. Written-first comms, demos, expectation-shaping, RACI.",
        yrs: "4 yrs",
        lvl: 0.84
      }
    ]
  }
];

function GroupIcon({ kind }) {
  const common = { width: 22, height: 22, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.6, strokeLinecap: "round" };
  if (kind === "stack") {
    return (
      <svg {...common}>
        <rect x="3" y="4" width="18" height="4" rx="1" />
        <rect x="3" y="10" width="18" height="4" rx="1" />
        <rect x="3" y="16" width="18" height="4" rx="1" />
        <circle cx="6.5" cy="6" r="0.6" fill="currentColor" stroke="none" />
        <circle cx="6.5" cy="12" r="0.6" fill="currentColor" stroke="none" />
        <circle cx="6.5" cy="18" r="0.6" fill="currentColor" stroke="none" />
      </svg>
    );
  }
  if (kind === "cloud") {
    return (
      <svg {...common}>
        <circle cx="8" cy="14" r="4" />
        <circle cx="14" cy="10" r="5" />
        <circle cx="18" cy="14" r="3.5" />
      </svg>
    );
  }
  if (kind === "data") {
    return (
      <svg {...common}>
        <ellipse cx="12" cy="6" rx="7" ry="2.5" />
        <path d="M5 6 V12 C5 13.4 8.1 14.5 12 14.5 C15.9 14.5 19 13.4 19 12 V6" />
        <path d="M5 12 V18 C5 19.4 8.1 20.5 12 20.5 C15.9 20.5 19 19.4 19 18 V12" />
      </svg>
    );
  }
  if (kind === "target") {
    return (
      <svg {...common}>
        <circle cx="12" cy="12" r="9" />
        <circle cx="12" cy="12" r="5" />
        <circle cx="12" cy="12" r="1.5" fill="currentColor" stroke="none" />
      </svg>
    );
  }
  return null;
}

function SkillCard({ skill, dragging, dragOver, innerRef, ...handlers }) {
  return (
    <div
      ref={innerRef}
      className={`skill-card ${dragging ? "dragging" : ""} ${dragOver ? "drag-over" : ""}`}
      style={{ "--lvl": skill.lvl }}
      draggable
      {...handlers}
    >
      <div className="skill-head">
        <div className="skill-cat">{skill.cat}</div>
        <div className="skill-grip" aria-hidden="true">
          <span></span><span></span>
          <span></span><span></span>
          <span></span><span></span>
        </div>
      </div>
      <h3 className="skill-name">{skill.name}</h3>
      <p className="skill-detail">{skill.detail}</p>
      <div className="skill-foot">
        <span>Drag to rearrange ↻</span>
        <span className="yrs">{skill.yrs}</span>
      </div>
    </div>
  );
}

function SkillGroup({ group }) {
  const [skills, setSkills] = useState(group.skills);
  const [draggingId, setDraggingId] = useState(null);
  const [overId, setOverId] = useState(null);
  const cardRefs = useRef({});

  useEffect(() => {
    const fallback = setTimeout(() => {
      Object.values(cardRefs.current).forEach((el) => el && el.classList.add("in"));
    }, 600);
    let io;
    try {
      io = new IntersectionObserver(
        (entries) => {
          entries.forEach((e) => {
            if (e.isIntersecting) {
              e.target.classList.add("in");
              clearTimeout(fallback);
            }
          });
        },
        { threshold: 0.25 }
      );
      Object.values(cardRefs.current).forEach((el) => el && io.observe(el));
    } catch (_) {
      Object.values(cardRefs.current).forEach((el) => el && el.classList.add("in"));
    }
    return () => { clearTimeout(fallback); io && io.disconnect(); };
  }, [skills]);

  const onDragStart = (id) => (e) => {
    setDraggingId(id);
    e.dataTransfer.effectAllowed = "move";
    e.dataTransfer.setData("text/plain", `${group.id}::${id}`);
  };
  const onDragOver = (id) => (e) => {
    const raw = e.dataTransfer.types.includes("text/plain") ? null : null;
    // only accept drops from same group — we can't read getData on dragOver, so check draggingId
    if (!draggingId) return;
    e.preventDefault();
    e.dataTransfer.dropEffect = "move";
    if (id !== overId) setOverId(id);
  };
  const onDragLeave = () => setOverId(null);
  const onDrop = (targetId) => (e) => {
    e.preventDefault();
    const raw = e.dataTransfer.getData("text/plain") || `${group.id}::${draggingId}`;
    const [grp, sourceId] = raw.split("::");
    if (grp !== group.id || !sourceId || sourceId === targetId) {
      setDraggingId(null); setOverId(null); return;
    }
    setSkills((curr) => {
      const next = [...curr];
      const fromIdx = next.findIndex((s) => s.id === sourceId);
      const toIdx = next.findIndex((s) => s.id === targetId);
      const [moved] = next.splice(fromIdx, 1);
      next.splice(toIdx, 0, moved);
      return next;
    });
    setDraggingId(null); setOverId(null);
  };
  const onDragEnd = () => { setDraggingId(null); setOverId(null); };

  return (
    <div className="skill-group">
      <div className="skill-group-head">
        <div className="skill-group-icon"><GroupIcon kind={group.icon} /></div>
        <div>
          <h3 className="skill-group-title">{group.title}</h3>
          <div className="skill-group-sub">{group.sub}</div>
        </div>
        <div className="skill-group-count">
          <span className="num">{String(skills.length).padStart(2, "0")}</span>
          <span className="lbl">skills</span>
        </div>
      </div>

      <div className="skills-grid">
        {skills.map((s) => (
          <SkillCard
            key={s.id}
            innerRef={(el) => (cardRefs.current[s.id] = el)}
            skill={s}
            dragging={draggingId === s.id}
            dragOver={overId === s.id && draggingId !== s.id}
            onDragStart={onDragStart(s.id)}
            onDragOver={onDragOver(s.id)}
            onDragLeave={onDragLeave}
            onDrop={onDrop(s.id)}
            onDragEnd={onDragEnd}
          />
        ))}
      </div>
    </div>
  );
}

function SkillsSection() {
  return (
    <section id="stack" className="section">
      <Reveal as="div" className="section-head">
        <div className="section-num">01 / Stack</div>
        <div>
          <h2 className="section-title">
            Built across the stack, <em>still curious.</em>
          </h2>
          <p className="section-sub">
            Grouped by what they actually do. Drag any card within a group to reorder by what matters most to you.
          </p>
        </div>
      </Reveal>

      <Reveal>
        <div className="skill-groups">
          {GROUPS.map((g) => <SkillGroup key={g.id} group={g} />)}
        </div>
      </Reveal>
    </section>
  );
}

Object.assign(window, { SkillsSection });
