/* DNS / MagicDNS — edits the `dns:` block of config.yaml as a DRAFT.
   The Headscale API does not mutate DNS; changes require a server reload/restart. */
function DNS() {
  const s = useStore();
  const toast = useToast();
  const d = s.dns;            // editable draft
  const applied = s.dnsApplied;
  const [nsInput, setNsInput] = useState("");
  const [sdInput, setSdInput] = useState("");
  const dirty = JSON.stringify(d) !== JSON.stringify(applied);

  const set = (patch) => HS.act.saveDnsDraft(patch);
  const addNs = () => { const v = nsInput.trim(); if (!v) return; set({ nameservers: { ...d.nameservers, global: [...d.nameservers.global, v] } }); setNsInput(""); };
  const rmNs = (ip) => set({ nameservers: { ...d.nameservers, global: d.nameservers.global.filter((x) => x !== ip) } });
  const addSd = () => { const v = sdInput.trim(); if (!v) return; set({ search_domains: [...d.search_domains, v] }); setSdInput(""); };
  const rmSd = (x) => set({ search_domains: d.search_domains.filter((y) => y !== x) });
  const addRecord = () => set({ extra_records: [...d.extra_records, { name: "", type: "A", value: "" }] });
  const setRecord = (i, patch) => set({ extra_records: d.extra_records.map((r, j) => j === i ? { ...r, ...patch } : r) });
  const rmRecord = (i) => set({ extra_records: d.extra_records.filter((_, j) => j !== i) });

  // base_domain must differ from server_url domain — common footgun
  const serverDomain = s.serverInfo.url.replace(/^https?:\/\//, "");
  const baseConflict = d.base_domain && serverDomain.endsWith(d.base_domain);
  const noGlobalNs = d.magic_dns && d.nameservers.global.length === 0;

  return (
    <div className="page fade-up">
      <div className="section-head">
        <div>
          <h2 style={{ fontSize: 19 }}>DNS</h2>
          <div className="sub">Edits <span className="code-inline">config.yaml → dns:</span> — applied on server reload</div>
        </div>
        <div className="spacer" />
        {dirty && <span className="badge warn">unsaved draft</span>}
        <button className="btn" disabled={!dirty} onClick={() => { HS.act.saveDnsDraft(JSON.parse(JSON.stringify(applied))); toast.push({ kind: "info", title: "Reverted to applied config" }); }}>Revert</button>
        <button className="btn primary" disabled={!dirty || baseConflict} onClick={() => { HS.act.applyDns(); toast.push({ kind: "success", title: "Config saved", msg: "Restart the coordination server to apply" }); }}><Ic name="refresh" size={15} />Apply (restarts server)</button>
      </div>

      {(baseConflict || noGlobalNs) && (
        <div style={{ marginBottom: 14, display: "flex", flexDirection: "column", gap: 8 }}>
          {baseConflict && <Banner cls="danger" icon="warn"><b>base_domain must differ from the server URL domain.</b> <span className="code-inline">{d.base_domain}</span> overlaps <span className="code-inline">{serverDomain}</span> — Headscale will refuse to start.</Banner>}
          {noGlobalNs && <Banner cls="warn" icon="info">MagicDNS is on but no global nameserver is set — name resolution for non-tailnet domains will fail.</Banner>}
        </div>
      )}

      <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14, alignItems: "start" }} className="dns-cols">
        {/* MagicDNS */}
        <div className="card card-pad" style={{ display: "flex", flexDirection: "column", gap: 14 }}>
          <div className="section-head" style={{ margin: 0 }}><Ic name="dns" size={17} style={{ color: "var(--accent)" }} /><h2>MagicDNS</h2><div className="spacer" /><span className={"toggle" + (d.magic_dns ? " on" : "")} onClick={() => set({ magic_dns: !d.magic_dns })} /></div>
          <p style={{ fontSize: 13, color: "var(--text-dim)", lineHeight: 1.5, marginTop: -6 }}>Devices resolve each other by name. <span className="code-inline">dns.magic_dns</span></p>
          <div className="field">
            <label>Base domain <span className="mono" style={{ color: "var(--text-faint)", fontWeight: 400 }}>dns.base_domain</span></label>
            <input className="input mono" value={d.base_domain} onChange={(e) => set({ base_domain: e.target.value })} style={{ borderColor: baseConflict ? "var(--danger)" : undefined }} />
            <span className="hint">e.g. <span className="code-inline">alice-mbp.{d.base_domain}</span> → 100.64.0.1</span>
          </div>
          <ToggleRow label="Override local DNS" desc="Force devices to use the nameservers below (dns.override_local_dns)" on={d.override_local_dns} set={(v) => set({ override_local_dns: v })} />
        </div>

        {/* Preview */}
        <div className="card card-pad" style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          <div className="section-head" style={{ margin: 0 }}><Ic name="globe" size={17} style={{ color: "var(--info)" }} /><h2>Name preview</h2></div>
          <div style={{ background: "var(--surface-2)", borderRadius: 9, padding: 12, display: "flex", flexDirection: "column", gap: 8, maxHeight: 200, overflowY: "auto" }}>
            {s.machines.slice(0, 6).map((m) => (
              <div key={m.id} style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 12.5 }}>
                <span className={"dot-status " + (m.online ? "online" : "offline")} style={{ width: 6, height: 6 }} />
                <span className="mono" style={{ flex: 1, overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{m.name}.{d.base_domain}</span>
                <span className="ip" style={{ fontSize: 11.5 }}>{m.ip4}</span>
              </div>
            ))}
          </div>
        </div>

        {/* Nameservers */}
        <div className="card card-pad" style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          <div className="section-head" style={{ margin: 0 }}><Ic name="server" size={17} style={{ color: "var(--text-dim)" }} /><h2>Global nameservers</h2></div>
          <div style={{ display: "flex", flexDirection: "column", gap: 7 }}>
            {d.nameservers.global.map((ip) => (
              <div key={ip} style={{ display: "flex", alignItems: "center", gap: 9, padding: "8px 11px", border: "1px solid var(--border)", borderRadius: 8 }}>
                <Ic name="globe" size={15} style={{ color: "var(--text-dim)" }} />
                <span className="ip" style={{ flex: 1 }}>{ip}</span>
                <span className="badge">{nsName(ip)}</span>
                <span className="copy-btn" onClick={() => rmNs(ip)}><Ic name="x" size={14} /></span>
              </div>
            ))}
          </div>
          <div style={{ display: "flex", gap: 8 }}>
            <input className="input mono" placeholder="1.1.1.1" value={nsInput} onChange={(e) => setNsInput(e.target.value)} onKeyDown={(e) => e.key === "Enter" && addNs()} />
            <button className="btn" onClick={addNs}><Ic name="plus" size={15} />Add</button>
          </div>
        </div>

        {/* Split DNS + search domains */}
        <div className="card card-pad" style={{ display: "flex", flexDirection: "column", gap: 12 }}>
          <div className="section-head" style={{ margin: 0 }}><Ic name="routes" size={17} style={{ color: "var(--text-dim)" }} /><h2>Split DNS &amp; search</h2></div>
          <div>
            <div style={{ fontSize: 12, color: "var(--text-faint)", fontWeight: 600, textTransform: "uppercase", letterSpacing: ".05em", marginBottom: 7 }}>Split nameservers <span className="mono" style={{ textTransform: "none" }}>dns.nameservers.split</span></div>
            {Object.entries(d.nameservers.split).map(([domain, servers]) => (
              <div key={domain} style={{ display: "flex", alignItems: "center", gap: 9, padding: "8px 11px", border: "1px solid var(--border)", borderRadius: 8, marginBottom: 6 }}>
                <span className="mono" style={{ fontSize: 12.5, flex: 1 }}>{domain}</span>
                <Ic name="chevRight" size={13} style={{ color: "var(--text-faint)" }} />
                <span className="ip">{servers.join(", ")}</span>
              </div>
            ))}
          </div>
          <div>
            <div style={{ fontSize: 12, color: "var(--text-faint)", fontWeight: 600, textTransform: "uppercase", letterSpacing: ".05em", marginBottom: 7 }}>Search domains</div>
            <div style={{ display: "flex", gap: 6, flexWrap: "wrap", marginBottom: 8 }}>
              {d.search_domains.map((x) => <span key={x} className="tag muted">{x}<span className="x" onClick={() => rmSd(x)}><Ic name="x" size={11} /></span></span>)}
            </div>
            <div style={{ display: "flex", gap: 8 }}>
              <input className="input mono" placeholder="example.org" value={sdInput} onChange={(e) => setSdInput(e.target.value)} onKeyDown={(e) => e.key === "Enter" && addSd()} />
              <button className="btn" onClick={addSd}><Ic name="plus" size={15} />Add</button>
            </div>
          </div>
        </div>

        {/* Extra records */}
        <div className="card card-pad" style={{ display: "flex", flexDirection: "column", gap: 12, gridColumn: "1 / -1" }}>
          <div className="section-head" style={{ margin: 0 }}><Ic name="dns" size={17} style={{ color: "var(--text-dim)" }} /><h2>Extra DNS records</h2><span className="sub" style={{ color: "var(--text-faint)" }}>custom A / AAAA published into MagicDNS</span><div className="spacer" /><button className="btn sm" onClick={addRecord}><Ic name="plus" size={14} />Add record</button></div>
          <div style={{ display: "flex", flexDirection: "column", gap: 7 }}>
            {d.extra_records.length === 0 && <div style={{ fontSize: 12.5, color: "var(--text-faint)" }}>No extra records.</div>}
            {d.extra_records.map((r, i) => (
              <div key={i} style={{ display: "flex", alignItems: "center", gap: 8 }}>
                <input className="input mono" style={{ flex: 2 }} placeholder="grafana.demo.net.ts" value={r.name} onChange={(e) => setRecord(i, { name: e.target.value })} />
                <div className="seg">
                  {["A", "AAAA"].map((t) => <button key={t} className={r.type === t ? "on" : ""} onClick={() => setRecord(i, { type: t })}>{t}</button>)}
                </div>
                <input className="input mono" style={{ flex: 1.4 }} placeholder="100.64.0.6" value={r.value} onChange={(e) => setRecord(i, { value: e.target.value })} />
                <button className="btn icon ghost" onClick={() => rmRecord(i)}><Ic name="trash" size={15} /></button>
              </div>
            ))}
          </div>
          <span className="hint">Inline <span className="code-inline">dns.extra_records</span> needs a restart; <span className="code-inline">dns.extra_records_path</span> (a watched JSON file) applies without one.</span>
        </div>

        {/* DERP (read-only) */}
        <div className="card card-pad" style={{ display: "flex", flexDirection: "column", gap: 12, gridColumn: "1 / -1" }}>
          <div className="section-head" style={{ margin: 0 }}><Ic name="globe" size={17} style={{ color: "var(--accent)" }} /><h2>DERP relays</h2><span className="badge" style={{ marginLeft: 6 }}>read-only · config file</span><div className="spacer" />{s.derp.embeddedServer && <span className="badge online"><span className="dot" />embedded server on</span>}</div>
          <div style={{ display: "grid", gridTemplateColumns: "repeat(auto-fill, minmax(220px,1fr))", gap: 10 }}>
            {s.derp.regions.map((rg) => (
              <div key={rg.id} style={{ border: "1px solid var(--border)", borderRadius: 9, padding: 12 }}>
                <div style={{ display: "flex", alignItems: "center", gap: 7, marginBottom: 7 }}><Ic name="server" size={15} style={{ color: "var(--text-dim)" }} /><b style={{ fontSize: 13 }}>{rg.name}</b><span className="badge" style={{ marginLeft: "auto" }}>#{rg.id}</span></div>
                {rg.nodes.map((n) => (
                  <div key={n.name} style={{ fontSize: 12, color: "var(--text-dim)", display: "flex", gap: 6 }}><span className="mono">{n.name}</span><span className="ip" style={{ marginLeft: "auto" }}>{n.ipv4}:{n.stun}</span></div>
                ))}
              </div>
            ))}
          </div>
        </div>
      </div>
      <style>{`@media (max-width: 860px){ .dns-cols{ grid-template-columns: 1fr; } }`}</style>
    </div>
  );
}
function Banner({ cls, icon, children }) {
  const color = cls === "danger" ? "var(--danger)" : "var(--warn)";
  const bg = cls === "danger" ? "var(--danger-soft)" : "var(--warn-soft)";
  return <div style={{ display: "flex", gap: 9, padding: "11px 13px", background: bg, color, borderRadius: 9, fontSize: 12.5, lineHeight: 1.5 }}><Ic name={icon} size={16} style={{ flexShrink: 0, marginTop: 1 }} /><div>{children}</div></div>;
}
function nsName(ip) {
  return ({ "1.1.1.1": "Cloudflare", "8.8.8.8": "Google", "8.8.4.4": "Google", "9.9.9.9": "Quad9" })[ip] || "Custom";
}
window.DNS = DNS;
window.Banner = Banner;
