/* SkyOps — New site wizard.
   Import (KML/KMZ/GeoJSON/SHP/DXF + asset CSV) or draw manually → location & boundary →
   asset details → zoning by drone capacity → review & create. */

const { useState: uSNS, useMemo: uMNS, useRef: uRNS } = React;

const NS_M = 2.5; // metres per SVG unit
const NS_SAMPLE = [[150,110],[620,80],[790,150],[820,360],[700,450],[330,470],[170,400],[120,240]];
const NS_SAMPLE_EXCL = [[430,250],[500,240],[510,300],[440,310]]; // substation
const NS_PLATFORMS = {
  "DJI M350 RTK · H30T": { min: 42, usable: 32, speed: 8 },
  "DJI M300 RTK · H20T": { min: 40, usable: 30, speed: 8 },
  "DJI Mavic 3T":        { min: 45, usable: 34, speed: 6 },
};
const nsArea = (p) => Math.abs(p.reduce((a, q, i) => { const r = p[(i + 1) % p.length]; return a + q[0] * r[1] - r[0] * q[1]; }, 0) / 2) * NS_M * NS_M;
const nsBBox = (p) => [Math.min(...p.map(q => q[0])), Math.min(...p.map(q => q[1])), Math.max(...p.map(q => q[0])), Math.max(...p.map(q => q[1]))];

function NewSitePage({ go, setActiveSite }) {
  const [step, setStep] = uSNS(0);
  const [src, setSrc] = uSNS(null);           // "import" | "draw"
  const [files, setFiles] = uSNS([]);
  const [poly, setPoly] = uSNS([]);
  const [closed, setClosed] = uSNS(false);
  const [excl, setExcl] = uSNS([]);
  const [info, setInfo] = uSNS({
    name: "", country: "PT", region: "Alentejo", lat: "38.5912", lng: "-7.8834", crs: "EPSG:25829 · ETRS89 / UTM 29N",
    mwp: "", mwac: "", modules: "", model: "Longi Hi-MO5 LR5-72HPH-550M", mount: "Single-axis tracker", tilt: "±55°", azimuth: "180°",
    inverters: "", invModel: "SMA Sunny Central 4600 UP", strings: "", cod: "2023-06-30", owner: "Iberdrola Renovables", operator: "Iberdrola O&M", grid: "400 kV · SE Évora Sul",
  });
  const [plat, setPlat] = uSNS("DJI M350 RTK · H30T");
  const [gsd, setGsd] = uSNS(3);
  const [perZone, setPerZone] = uSNS(4);
  const [orient, setOrient] = uSNS("cols");
  const [cadence, setCadence] = uSNS("Quarterly");
  const svgRef = uRNS(null);

  const set = (k) => (e) => setInfo(x => ({ ...x, [k]: e.target.value }));
  const area_m2 = closed && poly.length >= 3 ? nsArea(poly) - (excl.length >= 3 ? nsArea(excl) : 0) : 0;
  const area_ha = area_m2 / 1e4;
  const P = NS_PLATFORMS[plat];
  const haPerSortie = +(26 * Math.pow(gsd / 3, 2) * (P.usable / 32)).toFixed(1);
  const sorties = Math.ceil(area_ha / haPerSortie);
  const nZones = Math.max(1, Math.ceil(sorties / perZone));
  const flightDays = Math.ceil(sorties / 8);

  const [selZone, setSelZone] = uSNS(null);
  const zones = uMNS(() => {
    if (!closed || poly.length < 3) return [];
    const inPoly = (x, y, p) => { let c = false; for (let i = 0, j = p.length - 1; i < p.length; j = i++) { const [xi, yi] = p[i], [xj, yj] = p[j]; if ((yi > y) !== (yj > y) && x < (xj - xi) * (y - yi) / (yj - yi) + xi) c = !c; } return c; };
    const [x0, y0, x1, y1] = nsBBox(poly);
    const st = 4, pts = [];
    for (let x = x0 + st / 2; x < x1; x += st) for (let y = y0 + st / 2; y < y1; y += st)
      if (inPoly(x, y, poly) && !(excl.length >= 3 && inPoly(x, y, excl))) pts.push([x, y]);
    if (!pts.length) return [];
    const cuts = (arr, key, n) => { const s = [...arr].sort((a, b) => a[key] - b[key]); const out = []; for (let k = 1; k < n; k++) out.push(s[Math.floor(s.length * k / n)][key]); return out; };
    const cols = orient === "cols" ? nZones : Math.max(1, Math.round(Math.sqrt(nZones * (x1 - x0) / (y1 - y0))));
    const xc = cuts(pts, 0, cols);
    const colOf = (x) => xc.filter(c => x >= c).length;
    const groups = [];
    for (let c = 0; c < cols; c++) {
      const cp = pts.filter(p => colOf(p[0]) === c);
      const rows = orient === "cols" ? 1 : Math.max(1, Math.round(nZones / cols) + (c < nZones - cols * Math.round(nZones / cols) ? 1 : 0));
      const yc = cuts(cp, 1, rows);
      const xa = c === 0 ? x0 : xc[c - 1], xb = c === cols - 1 ? x1 : xc[c];
      for (let r = 0; r < rows; r++) {
        const zp = cp.filter(p => yc.filter(q => p[1] >= q).length === r);
        if (!zp.length) continue;
        const ya = r === 0 ? y0 : yc[r - 1], yb = r === rows - 1 ? y1 : yc[r];
        groups.push({ rect: [xa, ya, xb - xa, yb - ya], n: zp.length, cx: zp.reduce((a, p) => a + p[0], 0) / zp.length, cy: zp.reduce((a, p) => a + p[1], 0) / zp.length });
      }
    }
    const total = pts.length;
    return groups.map((g, i) => {
      const ha = area_ha * g.n / total;
      return { id: `Z${String(i + 1).padStart(2, "0")}`, x: g.rect[0], y: g.rect[1], w: g.rect[2], h: g.rect[3], cx: g.cx, cy: g.cy, ha, sorties: Math.max(1, Math.ceil(ha / haPerSortie)), hue: (i * 47) % 360 };
    });
  }, [closed, poly, excl, nZones, orient, area_ha, haPerSortie]);

  const toSvg = (e) => { const s = svgRef.current, p = s.createSVGPoint(); p.x = e.clientX; p.y = e.clientY; const r = p.matrixTransform(s.getScreenCTM().inverse()); return [Math.round(r.x), Math.round(r.y)]; };
  const onMapClick = (e) => {
    if (src !== "draw" || closed) return;
    const pt = toSvg(e);
    if (poly.length >= 3 && Math.hypot(pt[0] - poly[0][0], pt[1] - poly[0][1]) < 14) { setClosed(true); return; }
    setPoly(p => [...p, pt]);
  };
  const doImport = () => {
    setFiles([
      { n: "evora_norte_boundary.kmz", k: "Boundary", d: "1 polygon · 1 exclusion · WGS84" },
      { n: "evora_norte_layout.dxf", k: "CAD layout", d: "212 tables · 8 inverters · 1,410 strings" },
      { n: "asset_register.csv", k: "Asset list", d: "38,640 modules · serials + string IDs" },
    ]);
    setPoly(NS_SAMPLE); setExcl(NS_SAMPLE_EXCL); setClosed(true);
    setInfo(x => ({ ...x, name: x.name || "Évora Norte PV", mwp: "21.3", mwac: "18.4", modules: "38640", inverters: "8", strings: "1410" }));
  };
  const resetDraw = () => { setPoly([]); setClosed(false); setExcl([]); };

  const canNext = [!!src && (src === "draw" || files.length > 0), closed, !!info.name && !!info.mwp, true, true][step];
  const create = () => {
    const id = `${info.country.toLowerCase()}-${info.name.toLowerCase().replace(/[^a-z]/g, "").slice(0, 2)}-${String((window.SITES || []).length + 1).padStart(2, "0")}`;
    const site = {
      id, name: info.name, region: `${info.region}, ${info.country}`, country: info.country, type: "Solar",
      capacity_mw: +info.mwp || 0, panels: +info.modules || Math.round((+info.mwp || 0) * 1818), health: 100, criticals: 0, warnings: 0,
      lastInspection: "—", nextInspection: "—", irradiance: 900, ambient: 22, wind: 10, alerts: 0, coverage: 0, trend: "flat",
      area_ha: +area_ha.toFixed(1), zones: zones.map(z => ({ id: z.id, ha: +z.ha.toFixed(1), sorties: z.sorties, x: z.x, y: z.y, w: z.w, h: z.h, cx: z.cx, cy: z.cy })), poly, excl,
      model: info.model, mount: info.mount, tilt: info.tilt, azimuth: info.azimuth, inverters: +info.inverters || null, invModel: info.invModel, strings: +info.strings || null,
      mwac: +info.mwac || null, cod: info.cod, owner: info.owner, operator: info.operator, grid: info.grid, crs: info.crs, platform: plat, gsd, cadence, lat: info.lat, lng: info.lng,
    };
    window.SITES.push(site);
    try { const s = JSON.parse(localStorage.getItem("skyops_new_sites") || "[]"); s.push(site); localStorage.setItem("skyops_new_sites", JSON.stringify(s)); } catch {}
    setActiveSite(id); go("site");
    setTimeout(() => window.dispatchEvent(new CustomEvent("skyops:new-insp", { detail: { siteId: id } })), 300);
  };

  const STEPS = ["Source", "Location & boundary", "Asset details", "Zones & flight capacity", "Review"];
  const showMap = step === 1 || step === 3;

  return (
    <div className="page ns">
      <div className="page-head">
        <div className="title">
          <div className="kicker">Sites · onboarding</div>
          <h1>New site</h1>
          <div className="sub">Define where the asset is, what it contains, and how a drone will cover it.</div>
        </div>
        <div className="actions"><button className="btn btn-ghost" onClick={() => go("sites")}>Cancel</button></div>
      </div>

      <div className="ns-steps">
        {STEPS.map((s, i) => (
          <button key={s} className={`ni-step ${i === step ? "on" : ""} ${i < step ? "done" : ""}`} onClick={() => i < step && setStep(i)}>
            <i>{i < step ? <Icon name="check" size={9}/> : i + 1}</i>{s}
          </button>
        ))}
      </div>

      <div className={`ns-body ${showMap ? "with-map" : ""}`}>
        <div className="ns-form">
          {step === 0 && <>
            <h3 className="ns-h">How do you want to define the site?</h3>
            <div className="ns-src">
              <button className={`ns-opt ${src === "import" ? "on" : ""}`} onClick={() => setSrc("import")}>
                <Icon name="upload" size={18}/><b>Import files</b>
                <span>Boundary from KML / KMZ / GeoJSON / Shapefile, CAD layout (DXF/DWG) and asset register (CSV / SCADA export). Fastest for large sites — tables, strings and inverters come in with IDs.</span>
              </button>
              <button className={`ns-opt ${src === "draw" ? "on" : ""}`} onClick={() => { setSrc("draw"); setFiles([]); resetDraw(); }}>
                <Icon name="map" size={18}/><b>Draw on map</b>
                <span>Search the location and trace the fence line on satellite imagery. Asset details are typed in. Good for small sites or when no GIS data exists.</span>
              </button>
            </div>
            {src === "import" && <div className="ns-drop">
              {files.length === 0 ? <>
                <Icon name="upload" size={22}/>
                <div><b>Drop boundary, layout and asset files</b><span>.kml · .kmz · .geojson · .shp · .dxf · .dwg · .csv</span></div>
                <button className="btn btn-primary btn-xs" onClick={doImport}>Use sample files</button>
              </> : <div className="ns-files">
                {files.map(f => <div key={f.n} className="ns-file"><Icon name="check_circle" size={13}/><span className="mono">{f.n}</span><em>{f.k}</em><span className="sec">{f.d}</span></div>)}
                <div className="ns-files-note">Detected CRS EPSG:4326 → reprojected to EPSG:25829. Boundary, exclusions and asset hierarchy parsed.</div>
              </div>}
            </div>}
            <p className="ns-tip">Both work together: import what you have, then adjust the boundary or fill missing details manually.</p>
          </>}

          {step === 1 && <>
            <h3 className="ns-h">Location & boundary</h3>
            <div className="ns-search"><Icon name="search" size={12}/><input placeholder="Search address, parcel or coordinates" defaultValue="Évora, Portugal"/></div>
            <div className="ns-grid">
              <label className="field"><span>Latitude</span><input className="inp mono" value={info.lat} onChange={set("lat")}/></label>
              <label className="field"><span>Longitude</span><input className="inp mono" value={info.lng} onChange={set("lng")}/></label>
              <label className="field ns-span"><span>Projected CRS</span><select className="sel" value={info.crs} onChange={set("crs")}><option>EPSG:25829 · ETRS89 / UTM 29N</option><option>EPSG:25830 · ETRS89 / UTM 30N</option><option>EPSG:3763 · PT-TM06</option></select></label>
            </div>
            <div className="ns-stat-row">
              <div><span className="caps">Fenced area</span><b className="mono">{area_ha ? area_ha.toFixed(1) + " ha" : "—"}</b></div>
              <div><span className="caps">Vertices</span><b className="mono">{poly.length}</b></div>
              <div><span className="caps">Exclusions</span><b className="mono">{excl.length >= 3 ? 1 : 0}</b></div>
            </div>
            {src === "draw" && <div className="ns-tip">{closed ? "Boundary closed. Drag to adjust is available after creation." : "Click on the map to add fence vertices. Click the first point to close the polygon."}
              {poly.length > 0 && <button className="btn btn-ghost btn-xs" onClick={resetDraw}>Restart</button>}</div>}
            {src === "import" && <div className="ns-tip">Boundary and substation exclusion imported from <span className="mono">evora_norte_boundary.kmz</span>.</div>}
          </>}

          {step === 2 && <>
            <h3 className="ns-h">Asset details</h3>
            <div className="ns-sec-h">Identity</div>
            <div className="ns-grid">
              <label className="field ns-span"><span>Site name *</span><input className="inp" value={info.name} onChange={set("name")} placeholder="e.g. Évora Norte PV"/></label>
              <label className="field"><span>Country</span><select className="sel" value={info.country} onChange={set("country")}><option>PT</option><option>ES</option></select></label>
              <label className="field"><span>Region</span><input className="inp" value={info.region} onChange={set("region")}/></label>
              <label className="field"><span>Owner</span><input className="inp" value={info.owner} onChange={set("owner")}/></label>
              <label className="field"><span>O&M operator</span><input className="inp" value={info.operator} onChange={set("operator")}/></label>
            </div>
            <div className="ns-sec-h">Plant</div>
            <div className="ns-grid ns-grid-3">
              <label className="field"><span>DC capacity (MWp) *</span><input className="inp mono" value={info.mwp} onChange={set("mwp")}/></label>
              <label className="field"><span>AC capacity (MWac)</span><input className="inp mono" value={info.mwac} onChange={set("mwac")}/></label>
              <label className="field"><span>COD</span><input className="inp" type="date" value={info.cod} onChange={set("cod")}/></label>
              <label className="field"><span>Modules</span><input className="inp mono" value={info.modules} onChange={set("modules")}/></label>
              <label className="field ns-span2"><span>Module model</span><input className="inp" value={info.model} onChange={set("model")}/></label>
              <label className="field"><span>Mounting</span><select className="sel" value={info.mount} onChange={set("mount")}><option>Single-axis tracker</option><option>Fixed tilt</option><option>Rooftop</option><option>Floating</option></select></label>
              <label className="field"><span>Tilt</span><input className="inp mono" value={info.tilt} onChange={set("tilt")}/></label>
              <label className="field"><span>Azimuth</span><input className="inp mono" value={info.azimuth} onChange={set("azimuth")}/></label>
              <label className="field"><span>Inverters</span><input className="inp mono" value={info.inverters} onChange={set("inverters")}/></label>
              <label className="field ns-span2"><span>Inverter model</span><input className="inp" value={info.invModel} onChange={set("invModel")}/></label>
              <label className="field"><span>Strings</span><input className="inp mono" value={info.strings} onChange={set("strings")}/></label>
              <label className="field ns-span2"><span>Grid connection</span><input className="inp" value={info.grid} onChange={set("grid")}/></label>
            </div>
            <div className="ns-sec-h">Data sources</div>
            <div className="ns-conn">
              {[["SCADA","Bentek · inverter & string telemetry"],["Weather","Meteomatics · irradiance, wind"],["Market","OMIE spot · curtailment"]].map(([k,d]) => (
                <label key={k} className="ni-inh on"><input type="checkbox" defaultChecked/><span><b>{k}</b><em>{d}</em></span></label>
              ))}
            </div>
          </>}

          {step === 3 && <>
            <h3 className="ns-h">Zones & flight capacity</h3>
            <p className="ns-tip" style={{ marginTop: 0 }}>A large site can't be flown in one battery. Zones are sized to what a drone covers per sortie at the target resolution, so each zone is a flyable work package.</p>
            <div className="ns-grid">
              <label className="field ns-span"><span>Platform</span><select className="sel" value={plat} onChange={e => setPlat(e.target.value)}>{Object.keys(NS_PLATFORMS).map(p => <option key={p}>{p}</option>)}</select>
                <span className="hint">{P.min} min endurance · {P.usable} min usable per battery · {P.speed} m/s survey speed</span></label>
              <div className="field ns-span"><span>Thermal GSD target · <b className="mono">{gsd.toFixed(1)} cm/px</b></span><input type="range" min="2" max="6" step="0.5" value={gsd} onChange={e => setGsd(+e.target.value)}/>
                <span className="hint">IEC TS 62446-3 recommends ≤ 3 cm/px for cell-level thermal defects</span></div>
              <div className="field ns-span"><span>Sorties per zone · <b className="mono">{perZone}</b></span><input type="range" min="1" max="8" value={perZone} onChange={e => setPerZone(+e.target.value)}/>
                <span className="hint">Zones are cut to equal flyable area inside the fence, excluding the substation. Click a zone to highlight it.</span></div>
              <div className="field"><span>Zone layout</span><div className="ps-seg">{[["cols","Strips"],["grid","Grid"]].map(([k,l]) => <button key={k} className={orient === k ? "on" : ""} onClick={() => setOrient(k)}>{l}</button>)}</div></div>
              <div className="field"><span>Inspection cadence</span><select className="sel" value={cadence} onChange={e => setCadence(e.target.value)}><option>Monthly</option><option>Quarterly</option><option>Semi-annual</option><option>Annual</option></select></div>
            </div>
            <div className="ns-calc">
              <div><span className="caps">Coverage / sortie</span><b className="mono">{haPerSortie} ha</b></div>
              <div><span className="caps">Sorties needed</span><b className="mono">{sorties}</b></div>
              <div><span className="caps">Zones</span><b className="mono" style={{ color: "var(--accent-primary)" }}>{zones.length || nZones}</b><em>≈ {(area_ha / Math.max(1, zones.length || nZones)).toFixed(1)} ha each</em></div>
              <div><span className="caps">Flight days</span><b className="mono">{flightDays}</b><em>8 sorties / day</em></div>
            </div>
            {zones.some(z => z.sorties > perZone) && <div className="ns-zone-warn"><Icon name="alert" size={11}/>Some zones need more sorties than planned — add zones or lower the GSD target.</div>}
            <div className="ns-zlist">{zones.map(z => <div key={z.id} className={`ns-z ${selZone === z.id ? "on" : ""}`} onClick={() => setSelZone(z.id)}><i style={{ background: `hsl(${z.hue},70%,62%)` }}/><b className="mono">{z.id}</b><span className="mono sec">{z.ha.toFixed(1)} ha · {Math.round(z.ha / area_ha * 100)}% of site</span><span className={`mono ${z.sorties > perZone ? "warn" : "sec"}`}>{z.sorties} sorties · {Math.round(z.sorties * P.usable)} min</span></div>)}</div>
          </>}

          {step === 4 && <>
            <h3 className="ns-h">Review</h3>
            <div className="ns-review">
              {[["Site", info.name], ["Location", `${info.region}, ${info.country} · ${info.lat}, ${info.lng}`], ["Boundary", `${area_ha.toFixed(1)} ha · ${poly.length} vertices · ${excl.length >= 3 ? 1 : 0} exclusion`], ["Source", src === "import" ? `${files.length} files imported` : "Drawn manually"],
                ["Capacity", `${info.mwp} MWp / ${info.mwac || "—"} MWac`], ["Modules", `${info.modules || "—"} · ${info.model}`], ["Mounting", `${info.mount} · ${info.tilt} · ${info.azimuth}`], ["Inverters · strings", `${info.inverters || "—"} · ${info.strings || "—"}`],
                ["Owner · operator", `${info.owner} · ${info.operator}`], ["Zones", `${nZones} zones · ${sorties} sorties · ${flightDays} flight days`], ["Platform · GSD", `${plat} · ${gsd} cm/px`], ["Cadence", cadence]].map(([k, v]) => (
                <div key={k} className="ps-kv"><span>{k}</span><b>{v}</b></div>
              ))}
            </div>
            <p className="ns-tip">Creating the site opens it and starts the first inspection — the baseline every later cycle compares against.</p>
          </>}
        </div>

        {showMap && <div className="ns-map">
          <svg ref={svgRef} viewBox="0 0 940 560" preserveAspectRatio="xMidYMid meet" onClick={onMapClick} className={src === "draw" && !closed && step === 1 ? "is-draw" : ""}>
            <defs>
              <pattern id="ns-h" width="7" height="7" patternUnits="userSpaceOnUse" patternTransform="rotate(45)"><line x1="0" y1="0" x2="0" y2="7" stroke="#ef4444" strokeWidth="1.3" opacity=".8"/></pattern>
              <clipPath id="ns-clip"><polygon points={poly.map(p => p.join(",")).join(" ")}/></clipPath>
            </defs>
            <rect width="940" height="560" fill="#2b2f22"/>
            {Array.from({ length: 90 }).map((_, i) => <rect key={i} x={(i * 137) % 940} y={(i * 89) % 560} width={60 + (i % 5) * 20} height={40 + (i % 4) * 18} fill={i % 3 ? "#343826" : "#3a3a28"} opacity=".7"/>)}
            <path d="M0 500 C200 470 420 520 940 480" stroke="#5a5342" strokeWidth="10" fill="none"/>
            <path d="M880 0 L860 560" stroke="#5a5342" strokeWidth="6" fill="none"/>
            {closed && <g clipPath="url(#ns-clip)">{Array.from({ length: 34 }).map((_, i) => <rect key={i} x="100" y={90 + i * 11} width="740" height="6" fill="#1c2f48" opacity=".85"/>)}</g>}
            {poly.length > 0 && (closed
              ? <polygon points={poly.map(p => p.join(",")).join(" ")} fill="rgba(74,144,217,.08)" stroke="#60a5fa" strokeWidth="2"/>
              : <polyline points={poly.map(p => p.join(",")).join(" ")} fill="none" stroke="#60a5fa" strokeWidth="2" strokeDasharray="6 4"/>)}
            {excl.length >= 3 && <g><polygon points={excl.map(p => p.join(",")).join(" ")} fill="url(#ns-h)" stroke="#ef4444" strokeWidth="1.4"/><text x={excl[0][0]} y={excl[0][1] - 6} fontSize="10" fill="#fca5a5" fontFamily="var(--font-mono)">Substation · excluded</text></g>}
            {step === 3 && <g clipPath="url(#ns-clip)">{zones.map((z, i) => <g key={z.id}>
              <rect x={z.x} y={z.y} width={z.w} height={z.h} fill={`hsla(${z.hue},70%,55%,${selZone === z.id ? .34 : .16})`} stroke={`hsl(${z.hue},70%,62%)`} strokeWidth={selZone === z.id ? 3 : 1.6} strokeDasharray={selZone === z.id ? undefined : "5 3"} style={{ cursor: "pointer" }} onClick={() => setSelZone(z.id)}/>
            </g>)}</g>}
            {step === 3 && zones.map(z => <text key={z.id} x={z.cx} y={z.cy + 5} pointerEvents="none" textAnchor="middle" fontSize="14" fontWeight="700" fill="#f8fafc" fontFamily="var(--font-mono)" style={{ paintOrder: "stroke", stroke: "#0a0f1a", strokeWidth: 3 }}>{z.id}</text>)}
            {step === 1 && poly.map((p, i) => <circle key={i} cx={p[0]} cy={p[1]} r={i === 0 && !closed ? 7 : 4.5} fill={i === 0 && !closed && poly.length >= 3 ? "#fbbf24" : "#60a5fa"} stroke="#0a0f1a" strokeWidth="1.5"/>)}
            <g transform="translate(900 36)"><circle r="16" fill="rgba(10,14,26,.85)" stroke="#334155"/><path d="M0 -11 L5 4 L0 1 L-5 4 Z" fill="#ef4444"/><text y="13" textAnchor="middle" fontSize="7" fill="#94a3b8">N</text></g>
            <g transform="translate(24 530)"><rect width="80" height="4" fill="#e2e8f0"/><text y="-6" fontSize="10" fill="#cbd5e1" fontFamily="var(--font-mono)">200 m</text></g>
          </svg>
          {src === "draw" && poly.length === 0 && step === 1 && <div className="ns-map-hint"><Icon name="crosshair" size={13}/>Click to place the first fence vertex</div>}
          {area_ha > 0 && <div className="ns-map-badge mono">{area_ha.toFixed(1)} ha{step === 3 ? ` · ${nZones} zones` : ""}</div>}
        </div>}
      </div>

      <div className="ns-ft">
        {step > 0 && <button className="btn btn-ghost" onClick={() => setStep(step - 1)}>Back</button>}
        <span className="grow"/>
        {!canNext && <span className="sec ns-req">{["Choose a source", "Close the boundary polygon", "Name and DC capacity are required"][step]}</span>}
        {step < 4 ? <button className="btn btn-primary" disabled={!canNext} onClick={() => setStep(step + 1)}>Next<Icon name="arrow_right" size={12}/></button>
          : <button className="btn btn-primary" onClick={create}><Icon name="check" size={12}/>Create site & plan first inspection</button>}
      </div>
    </div>
  );
}

(() => { try { JSON.parse(localStorage.getItem("skyops_new_sites") || "[]").forEach(s => { if (!(window.SITES || []).find(x => x.id === s.id)) window.SITES.push(s); }); } catch {} })();
window.NewSitePage = NewSitePage;

/* Normalised site profile — same fields for wizard-created and seed sites (used by Site + Plan) */
function siteProfile(site) {
  if (!site) return null;
  const P = NS_PLATFORMS[site.platform] || NS_PLATFORMS["DJI M350 RTK · H30T"];
  const gsd = site.gsd || 3;
  const lastMic = (window.INSPECTIONS || []).find(i => i.siteId === site.id && i.area_ha);
  const area = site.area_ha || (lastMic && lastMic.area_ha) || +(site.capacity_mw * 1.96).toFixed(1);
  const haPerSortie = +(26 * Math.pow(gsd / 3, 2) * (P.usable / 32)).toFixed(1);
  const poly = site.poly || NS_SAMPLE;
  let zones = site.zones && site.zones.length && site.zones[0].ha ? site.zones : null;
  if (!zones) {
    const n = Math.max(1, Math.ceil(Math.ceil(area / haPerSortie) / 4));
    const [x0, y0, x1, y1] = nsBBox(poly), w = (x1 - x0) / n;
    zones = Array.from({ length: n }).map((_, i) => ({ id: `Z${String(i + 1).padStart(2, "0")}`, ha: +(area / n).toFixed(1), sorties: Math.ceil(area / n / haPerSortie), x: x0 + i * w, y: y0, w, h: y1 - y0, cx: x0 + (i + .5) * w, cy: (y0 + y1) / 2 }));
  }
  zones = zones.map((z, i) => ({ hue: (i * 47) % 360, ...z }));
  return {
    platform: site.platform || "DJI M350 RTK · H30T", P, gsd, area, haPerSortie, poly, excl: site.excl !== undefined ? site.excl : (site.poly ? [] : NS_SAMPLE_EXCL), zones,
    modules: site.panels, model: site.model || "Longi Hi-MO5 LR5-72HPH-550M", mount: site.mount || "Single-axis tracker",
    tilt: site.tilt || "±55°", azimuth: site.azimuth || "180°", inverters: site.inverters || Math.max(1, Math.round(site.capacity_mw / 4.6)),
    invModel: site.invModel || "SMA Sunny Central 4600 UP", strings: site.strings || Math.round(site.panels / 28),
    mwac: site.mwac || +(site.capacity_mw * 0.86).toFixed(1), cod: site.cod || "2021-06-30", owner: site.owner || "Iberdrola Renovables",
    operator: site.operator || "Iberdrola O&M", grid: site.grid || "—", cadence: site.cadence || "Quarterly",
    lat: site.lat || "38.5729", lng: site.lng || "-7.9162", crs: site.crs || "EPSG:25829 · ETRS89 / UTM 29N",
  };
}
window.siteProfile = siteProfile;
window.NS = { NS_M, NS_SAMPLE, NS_SAMPLE_EXCL, NS_PLATFORMS };
