import { useEffect, useState } from "react";
import { motion, AnimatePresence } from "framer-motion";
import {
  User,
  Server,
  KeyRound,
  UserCircle,
  Link as LinkIcon,
  Loader2,
  Globe2,
  Check,
  Plus,
  Upload,
  FileText,
  X,
  Trash2,
  Cpu,
} from "lucide-react";
import { useTranslation } from "react-i18next";
import type { ProfileKind, ProfileTarget } from "@/types/xtream";
import { apiListSharedProfiles, type SharedProfile } from "@/lib/nadiAuth";
import { useAuth } from "@/hooks/useAuth";
import StalkerTestButton from "@/components/StalkerTestButton";
import DpadHelperOverlay from "@/components/DpadHelperOverlay";
import {
  FocusableButton,
  FocusableSection,
  FocusableInput,
  setFocus,
} from "@/components/focusable";
import { useFocusRestore } from "@/hooks/useFocusRestore";

export interface AddServerData {
  kind: ProfileKind;
  name: string;
  serverUrl: string;
  username: string;
  password: string;
  m3uUrl?: string;
  m3uContent?: string;
  portalUrl?: string;
  macAddress?: string;
  /** Target section: "all" (default), "live", or "vod" */
  target?: ProfileTarget;
}

interface Props {
  open: boolean;
  onClose: () => void;
  onSubmit: (data: AddServerData) => void | Promise<void>;
}

type Advanced = "shared" | "own";

interface M3URow {
  key: string;
  name: string;
  url: string;
  content: string;
  fileName: string;
}

const newRow = (): M3URow => ({
  key: `r-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
  name: "",
  url: "",
  content: "",
  fileName: "",
});

const AddServerDialog = ({ open, onClose, onSubmit }: Props) => {
  const { t } = useTranslation();
  const { user, isGuest: authIsGuest } = useAuth();
  const isGuest = authIsGuest || !user;

  const [kind, setKind] = useState<ProfileKind>("xtream");
  // Default to "own" mode for EVERYONE — guests, premium users, admins alike.
  // The dialog will auto-switch to "shared" only if the profile list comes
  // back with at least one admin-provisioned profile. This guarantees
  // premium subscribers NEVER see the upgrade pitch and always land on
  // the actual URL / Username / Password input form.
  const [advanced, setAdvanced] = useState<Advanced>("own");

  // Xtream / single-name fields
  const [name, setName] = useState("");
  const [serverUrl, setServerUrl] = useState("");
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");

  // Stalker / MAC fields
  const [portalUrl, setPortalUrl] = useState("");
  const [macAddress, setMacAddress] = useState("");

  // M3U mode supports multiple rows ("+ ADD PLAYLIST")
  const [m3uRows, setM3uRows] = useState<M3URow[]>([newRow()]);

  const [submitting, setSubmitting] = useState(false);
  const [target, setTarget] = useState<ProfileTarget>("all");

  // Profiles provisioned by admin — only fetched for logged-in users
  const [profiles, setProfiles] = useState<SharedProfile[]>([]);
  const [profilesLoading, setProfilesLoading] = useState(false);
  const [profilesError, setProfilesError] = useState<string | null>(null);
  const [selectedProfileId, setSelectedProfileId] = useState<string | null>(null);

  const reset = () => {
    setName("");
    setServerUrl("");
    setUsername("");
    setPassword("");
    setM3uRows([newRow()]);
    setSelectedProfileId(null);
    setPortalUrl("");
    setMacAddress("");
    setTarget("all");
  };

  // Fetch admin-configured profiles when dialog opens (logged-in only)
  useEffect(() => {
    if (!open || isGuest) return;
    let cancelled = false;
    setProfilesLoading(true);
    setProfilesError(null);
    apiListSharedProfiles()
      .then((res) => {
        if (cancelled) return;
        const list = res.profiles || [];
        setProfiles(list);
        // If the admin HAS provisioned at least one shared profile, switch
        // the dialog into "shared" mode so the user can pick from the list.
        // Otherwise leave `advanced` on the default "own" and render the
        // full Xtream / M3U / Stalker form right away — no upgrade pitch.
        if (list.length > 0) setAdvanced("shared");
      })
      .catch((e) => {
        if (!cancelled) {
          setProfilesError(e instanceof Error ? e.message : "Failed");
          // If we can't even load the profile list, fall back to the own-
          // server form so the user can still enter their credentials.
          setAdvanced("own");
        }
      })
      .finally(() => {
        if (!cancelled) setProfilesLoading(false);
      });
    return () => {
      cancelled = true;
    };
  }, [open, isGuest]);

  // Reset state on close.  We always land back on the "own" form so the
  // next open shows inputs immediately — the profile-fetch effect will
  // flip to "shared" only if admin-provisioned profiles actually exist.
  useEffect(() => {
    if (!open) {
      setAdvanced("own");
      setKind("xtream");
      reset();
    }
  }, [open]);

  // When user picks a shared profile → autofill all fields
  const pickProfile = (p: SharedProfile) => {
    setSelectedProfileId(p.id || p.name);
    setName(p.name || "");
    if (p.kind === "m3u") {
      setKind("m3u");
      setM3uRows([
        {
          key: `r-${Date.now()}`,
          name: p.name || "",
          url: p.m3u_url || "",
          content: p.m3u_content || "",
          fileName: p.m3u_content ? "shared.m3u" : "",
        },
      ]);
    } else if (p.kind === "stalker") {
      setKind("stalker");
      setPortalUrl(p.portal_url || "");
      setMacAddress(p.mac_address || "");
    } else {
      setKind("xtream");
      setServerUrl(p.server || "");
      setUsername(p.username || "");
      setPassword(p.password || "");
    }
  };

  const updateRow = (idx: number, patch: Partial<M3URow>) =>
    setM3uRows((prev) => prev.map((r, i) => (i === idx ? { ...r, ...patch } : r)));

  const addRow = () => setM3uRows((prev) => [...prev, newRow()]);
  const removeRow = (idx: number) =>
    setM3uRows((prev) => (prev.length > 1 ? prev.filter((_, i) => i !== idx) : prev));

  const handleFile = async (idx: number, file: File | null) => {
    if (!file) return;
    const text = await file.text();
    updateRow(idx, { content: text, fileName: file.name });
  };

  const clearFile = (idx: number) => updateRow(idx, { content: "", fileName: "" });

  const handleSubmit = async () => {
    const activeKind =
      advanced === "shared" && selectedProfileId
        ? profiles.find((p) => (p.id || p.name) === selectedProfileId)?.kind || kind
        : kind;

    if (activeKind === "xtream") {
      if (!name) return;
      if (!serverUrl || !username || !password) return;
      setSubmitting(true);
      try {
        await onSubmit({
          kind: "xtream",
          name,
          serverUrl,
          username,
          password,
          target,
        });
        reset();
      } finally {
        setSubmitting(false);
      }
      return;
    }

    if (activeKind === "stalker") {
      const macOk = /^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$/.test(macAddress.trim());
      if (!name || !portalUrl.trim() || !macOk) return;
      setSubmitting(true);
      try {
        await onSubmit({
          kind: "stalker",
          name,
          serverUrl: "",
          username: "",
          password: "",
          portalUrl: portalUrl.trim(),
          macAddress: macAddress.trim().toUpperCase(),
          target,
        });
        reset();
      } finally {
        setSubmitting(false);
      }
      return;
    }

    // M3U: submit each row that has a URL or file content as a separate playlist
    const valid = m3uRows
      .map((r) => ({
        ...r,
        name: (r.name || name || "").trim(),
        url: r.url.trim(),
        content: r.content,
      }))
      .filter((r) => r.url.length > 0 || r.content.trim().length > 0)
      .map((r, i, arr) => ({
        ...r,
        // Auto-name when blank
        name: r.name || (arr.length > 1 ? `Playlist ${i + 1}` : "M3U Playlist"),
      }));

    if (valid.length === 0) return;

    setSubmitting(true);
    try {
      for (const r of valid) {
        await onSubmit({
          kind: "m3u",
          name: r.name,
          serverUrl: "",
          username: "",
          password: "",
          m3uUrl: r.url || undefined,
          m3uContent: r.content || undefined,
          target,
        });
      }
      reset();
    } finally {
      setSubmitting(false);
    }
  };

  const sharedReady =
    advanced === "shared" && selectedProfileId !== null && !profilesLoading;
  const submitDisabled =
    submitting || (advanced === "shared" && !isGuest && !sharedReady);

  // ON CLOSE — restore focus to the element that opened the modal.
  // We capture the previously-focused norigin key when `open` flips
  // true, and walk a fallback list on close. Without this the app
  // would freeze on dismiss because focus was left on the destroyed
  // modal section.
  useFocusRestore(open, [
    "home-header-add",
    "livetv-add-profile-btn",
    "movies-add-profile-btn",
    "series-add-profile-btn",
    "owned-profiles-add-btn",
    "tv-back-button",
  ]);

  // When the dialog opens, explicitly lock D-pad focus on the FIRST
  // interactive control inside the modal — the Xtream/M3U/Stalker
  // tab row. autoFocus alone isn't reliable on every screen because
  // norigin's "closest to origin" heuristic sometimes picks the
  // Save button if the modal is rendered after layout-shift.
  useEffect(() => {
    if (!open) return;
    const tryFocus = () => {
      try {
        const target =
          advanced === "shared" ? "add-mode-shared" : `add-kind-${kind}`;
        setFocus(target);
      } catch {
        /* spatial-nav not ready */
      }
    };
    const t1 = window.setTimeout(tryFocus, 100);
    const t2 = window.setTimeout(tryFocus, 320);
    return () => {
      window.clearTimeout(t1);
      window.clearTimeout(t2);
    };
  }, [open, advanced, kind]);

  // Close on Escape / TV-back at the document level — see
  // LanguageSelect for the rationale (norigin's virtual focus
  // model means no DOM node inside the modal has browser focus
  // until the user starts typing in a field, so a wrapper-level
  // keydown listener doesn't fire reliably).
  useEffect(() => {
    if (!open) return;
    const handler = (e: KeyboardEvent) => {
      if (
        e.key === "Escape" ||
        e.keyCode === 10009 /* Tizen Return */ ||
        e.keyCode === 461 /* WebOS Back */
      ) {
        e.preventDefault();
        e.stopPropagation();
        onClose();
      }
    };
    document.addEventListener("keydown", handler, true);
    return () => document.removeEventListener("keydown", handler, true);
  }, [open, onClose]);

  return (
    <AnimatePresence>
      {open && (
        <motion.div
          initial={{ opacity: 0 }}
          animate={{ opacity: 1 }}
          exit={{ opacity: 0 }}
          className="fixed inset-0 z-50 flex items-end sm:items-center justify-center"
          onClick={onClose}
        >
          <div className="absolute inset-0 bg-black/60 backdrop-blur-sm" />
          <FocusableSection
            focusKey="add-server-modal"
            autoFocus
            trap
            onClick={(e) => e.stopPropagation()}
            onKeyDown={(e) => {
              if (
                e.key === "Escape" ||
                e.keyCode === 10009 /* Tizen Return */ ||
                e.keyCode === 461 /* WebOS Back */
              ) {
                e.preventDefault();
                e.stopPropagation();
                onClose();
              }
            }}
            className="relative glass-card rounded-t-3xl sm:rounded-3xl p-5 sm:p-8 w-full sm:max-w-lg mx-0 sm:mx-4 max-h-[90vh] overflow-y-auto"
          >
            <h2
              data-testid="add-server-title"
              className="text-foreground text-xl sm:text-2xl font-display tracking-[0.2em] gold-text text-center mb-5"
            >
              {t("addServer.title")}
            </h2>

            {/* Advanced toggle — ONLY for logged-in users with admin-configured profiles */}
            {!isGuest && profiles.length > 0 && (
              <div className="mb-4">
                <label className="text-[11px] text-muted-foreground tracking-[0.25em] uppercase block mb-2">
                  {t("addServer.advanced")}
                </label>
                <div className="flex glass rounded-xl p-1 gap-1">
                  <FocusableButton
                    focusKey="add-mode-shared"
                    onEnter={() => setAdvanced("shared")}
                    onClick={() => setAdvanced("shared")}
                    data-testid="add-mode-shared"
                    className={`flex-1 py-2 rounded-lg text-xs font-medium transition-all flex items-center justify-center gap-2 ${
                      advanced === "shared"
                        ? "bg-primary/20 text-primary"
                        : "text-muted-foreground"
                    }`}
                  >
                    <Globe2 className="w-3.5 h-3.5" />
                    {t("addServer.shared")}
                  </FocusableButton>
                  <FocusableButton
                    focusKey="add-mode-own"
                    onEnter={() => {
                      setAdvanced("own");
                      setSelectedProfileId(null);
                      reset();
                    }}
                    onClick={() => {
                      setAdvanced("own");
                      setSelectedProfileId(null);
                      reset();
                    }}
                    data-testid="add-mode-own"
                    className={`flex-1 py-2 rounded-lg text-xs font-medium transition-all flex items-center justify-center gap-2 ${
                      advanced === "own"
                        ? "bg-primary/20 text-primary"
                        : "text-muted-foreground"
                    }`}
                  >
                    <Server className="w-3.5 h-3.5" />
                    {t("addServer.ownServer")}
                  </FocusableButton>
                </div>
              </div>
            )}

            {/* SHARED MODE — pick an admin-provided profile */}
            {!isGuest && advanced === "shared" ? (
              <div className="space-y-2" data-testid="shared-profile-picker">
                {profilesLoading && (
                  <div className="text-xs text-muted-foreground flex items-center gap-2 py-2">
                    <Loader2 className="w-3 h-3 animate-spin" /> Loading profiles…
                  </div>
                )}
                {profilesError && (
                  <div className="text-destructive text-xs">{profilesError}</div>
                )}
                {!profilesLoading && profiles.length === 0 && (
                  <div
                    className="text-muted-foreground text-xs bg-muted/30 border border-border rounded-lg px-3 py-3"
                    data-testid="add-server-no-shared-empty"
                  >
                    {t(
                      "addServer.noSharedAvailable",
                      "No shared profile has been provisioned for your account yet. Enter your own credentials below.",
                    )}
                  </div>
                )}
                {!profilesLoading &&
                  profiles.map((p) => {
                    const id = p.id || p.name;
                    const active = selectedProfileId === id;
                    return (
                      <FocusableButton
                        key={id}
                        focusKey={`profile-pick-${id}`}
                        onEnter={() => pickProfile(p)}
                        onClick={() => pickProfile(p)}
                        data-testid={`profile-pick-${id}`}
                        className={`w-full flex items-center gap-3 px-3 py-2.5 rounded-xl border text-left transition-all ${
                          active
                            ? "bg-primary/10 border-primary/50"
                            : "glass border-transparent hover:border-primary/30"
                        }`}
                      >
                        {p.kind === "m3u" ? (
                          <LinkIcon className="w-4 h-4 text-primary shrink-0" />
                        ) : p.kind === "stalker" ? (
                          <Cpu className="w-4 h-4 text-primary shrink-0" />
                        ) : (
                          <Server className="w-4 h-4 text-primary shrink-0" />
                        )}
                        <div className="flex-1 min-w-0">
                          <p
                            className={`text-sm font-medium truncate ${
                              active ? "text-primary" : "text-foreground"
                            }`}
                          >
                            {p.name}
                          </p>
                          <p className="text-[10px] text-muted-foreground uppercase tracking-widest">
                            {p.kind === "m3u"
                              ? p.m3u_content
                                ? "M3U file (shared)"
                                : "M3U playlist"
                              : p.kind === "stalker"
                                ? "Stalker / MAC portal"
                                : "Xtream codes"}
                          </p>
                        </div>
                        {active && <Check className="w-4 h-4 text-primary" />}
                      </FocusableButton>
                    );
                  })}
              </div>
            ) : (
              // OWN MODE — guest always lands here; logged-in "Own" tab too.
              <>
                <div className="flex glass rounded-xl p-1 mb-4 gap-1">
                  {(["xtream", "m3u", "stalker"] as ProfileKind[]).map((k) => (
                    <FocusableButton
                      key={k}
                      focusKey={`add-kind-${k}`}
                      onEnter={() => setKind(k)}
                      onClick={() => setKind(k)}
                      data-testid={`add-kind-${k}`}
                      className={`flex-1 py-2 rounded-lg text-xs font-medium transition-all ${
                        kind === k
                          ? "bg-primary/20 text-primary"
                          : "text-muted-foreground"
                      }`}
                    >
                      {k === "xtream"
                        ? t("addServer.xtreamTab")
                        : k === "m3u"
                          ? t("addServer.m3uTab")
                          : "Stalker / MAC"}
                    </FocusableButton>
                  ))}
                </div>

                {/* Target selector: what section this playlist is for */}
                <div className="flex glass rounded-xl p-1 mb-4 gap-1">
                  {([
                    { val: "all" as const, label: "All Content", color: "bg-primary/20 text-primary" },
                    { val: "live" as const, label: "Live TV", color: "bg-emerald-500/20 text-emerald-400" },
                    { val: "vod" as const, label: "Movies & Series", color: "bg-blue-500/20 text-blue-400" },
                  ]).map(({ val, label, color }) => (
                    <FocusableButton
                      key={val}
                      focusKey={`add-target-${val}`}
                      type="button"
                      onEnter={() => setTarget(val)}
                      onClick={() => setTarget(val)}
                      data-testid={`add-target-${val}`}
                      className={`flex-1 py-2 rounded-lg text-[10px] font-bold tracking-wide transition-all ${
                        target === val ? color : "text-muted-foreground"
                      }`}
                    >
                      {label}
                    </FocusableButton>
                  ))}
                </div>

                {kind === "xtream" ? (
                  <div className="space-y-3">
                    <Field
                      focusKey="add-name"
                      icon={UserCircle}
                      placeholder={t("addServer.profileNamePlaceholder")}
                      value={name}
                      onChange={setName}
                      testId="add-name"
                      onArrowDownFocusKey="add-server-url"
                    />
                    <Field
                      focusKey="add-server-url"
                      icon={Server}
                      placeholder={t("addServer.serverUrlPlaceholder")}
                      value={serverUrl}
                      onChange={setServerUrl}
                      testId="add-server-url"
                      onArrowUpFocusKey="add-name"
                      onArrowDownFocusKey="add-user"
                    />
                    <Field
                      focusKey="add-user"
                      icon={User}
                      placeholder={t("addServer.usernamePlaceholder")}
                      value={username}
                      onChange={setUsername}
                      testId="add-user"
                      onArrowUpFocusKey="add-server-url"
                      onArrowDownFocusKey="add-pass"
                    />
                    <Field
                      focusKey="add-pass"
                      icon={KeyRound}
                      placeholder={t("addServer.passwordPlaceholder")}
                      value={password}
                      onChange={setPassword}
                      type="password"
                      testId="add-pass"
                      onArrowUpFocusKey="add-user"
                      onArrowDownFocusKey="add-submit"
                    />
                  </div>
                ) : kind === "stalker" ? (
                  <div className="space-y-3" data-testid="stalker-form">
                    <Field
                      focusKey="add-stalker-name"
                      icon={UserCircle}
                      placeholder={t("addServer.profileNamePlaceholder")}
                      value={name}
                      onChange={setName}
                      testId="add-stalker-name"
                      onArrowDownFocusKey="add-stalker-portal"
                    />
                    <Field
                      focusKey="add-stalker-portal"
                      icon={Globe2}
                      placeholder="Portal URL (e.g. http://portal.com:8080/c/)"
                      value={portalUrl}
                      onChange={setPortalUrl}
                      testId="add-stalker-portal"
                      onArrowUpFocusKey="add-stalker-name"
                      onArrowDownFocusKey="add-stalker-mac"
                    />
                    <Field
                      focusKey="add-stalker-mac"
                      icon={Cpu}
                      placeholder="MAC Address (00:1A:79:XX:XX:XX)"
                      value={macAddress}
                      onChange={(v) => setMacAddress(formatMac(v))}
                      testId="add-stalker-mac"
                      onArrowUpFocusKey="add-stalker-portal"
                      onArrowDownFocusKey="add-submit"
                    />
                    <StalkerTestButton
                      portalUrl={portalUrl}
                      mac={macAddress}
                      testId="add-stalker-test"
                    />
                    <p className="text-[11px] text-muted-foreground leading-relaxed px-1">
                      Stalker / MAG portal login. The app impersonates a MAG250
                      set-top box (User-Agent: <code>QtStalker</code>,
                      X-User-Agent: <code>Model: MAG250</code>) and authenticates
                      using your MAC address.
                    </p>
                  </div>
                ) : (
                  // M3U mode — multiple rows, with optional file upload
                  <div className="space-y-3">
                    {m3uRows.map((row, idx) => (
                      <div
                        key={row.key}
                        data-testid={`m3u-row-${idx}`}
                        className="glass rounded-xl p-3 border border-border/40 space-y-2"
                      >
                        <div className="flex items-center justify-between">
                          <span className="text-[10px] uppercase tracking-widest text-primary/80">
                            Playlist #{idx + 1}
                          </span>
                          {m3uRows.length > 1 && (
                            <button
                              type="button"
                              onClick={() => removeRow(idx)}
                              data-testid={`m3u-row-remove-${idx}`}
                              className="text-muted-foreground hover:text-destructive transition-colors"
                              aria-label="Remove row"
                            >
                              <Trash2 className="w-3.5 h-3.5" />
                            </button>
                          )}
                        </div>
                        <Field
                          focusKey={`add-m3u-name-${idx}`}
                          icon={UserCircle}
                          placeholder={t("addServer.profileNamePlaceholder")}
                          value={row.name}
                          onChange={(v) => updateRow(idx, { name: v })}
                          testId={`add-m3u-name-${idx}`}
                          onArrowDownFocusKey={`add-m3u-url-${idx}`}
                        />
                        <Field
                          focusKey={`add-m3u-url-${idx}`}
                          icon={LinkIcon}
                          placeholder={t("addServer.m3uPlaceholder")}
                          value={row.url}
                          onChange={(v) => updateRow(idx, { url: v })}
                          testId={`add-m3u-url-${idx}`}
                          onArrowUpFocusKey={`add-m3u-name-${idx}`}
                        />
                        <div className="flex items-center gap-2 flex-wrap">
                          <label
                            data-testid={`add-m3u-file-${idx}`}
                            className="cursor-pointer flex items-center gap-2 px-3 py-2 rounded-lg glass text-xs text-primary hover:border-primary/40 transition-colors"
                          >
                            <Upload className="w-3.5 h-3.5" />
                            <span>Upload .m3u file</span>
                            <input
                              type="file"
                              accept=".m3u,.m3u8,audio/x-mpegurl,application/vnd.apple.mpegurl,text/plain"
                              onChange={(e) =>
                                void handleFile(idx, e.target.files?.[0] ?? null)
                              }
                              className="hidden"
                            />
                          </label>
                          {row.content && row.content.trim().length > 0 && (
                            <div className="flex items-center gap-2 flex-1 min-w-0 text-xs text-muted-foreground">
                              <FileText className="w-3.5 h-3.5 text-primary shrink-0" />
                              <span className="truncate">
                                {row.fileName || "uploaded.m3u"}
                              </span>
                              <button
                                type="button"
                                onClick={() => clearFile(idx)}
                                data-testid={`add-m3u-file-clear-${idx}`}
                                className="ml-1 text-muted-foreground hover:text-destructive"
                              >
                                <X className="w-3.5 h-3.5" />
                              </button>
                            </div>
                          )}
                        </div>
                      </div>
                    ))}

                    <FocusableButton
                      focusKey="add-m3u-row-btn"
                      type="button"
                      onEnter={addRow}
                      onClick={addRow}
                      data-testid="add-m3u-row-btn"
                      className="w-full flex items-center justify-center gap-2 py-2.5 rounded-xl border border-dashed border-primary/40 text-primary hover:bg-primary/10 transition-colors text-xs font-medium tracking-[0.2em] uppercase"
                    >
                      <Plus className="w-4 h-4" /> Add Playlist
                    </FocusableButton>
                  </div>
                )}
              </>
            )}

            <div className="flex flex-col sm:flex-row gap-3 mt-6">
              <FocusableButton
                focusKey="add-submit"
                onEnter={() => void handleSubmit()}
                onClick={() => void handleSubmit()}
                loading={submitting}
                disabled={submitDisabled}
                data-testid="add-submit"
                className="flex-1 bg-primary/80 hover:bg-primary text-primary-foreground font-medium py-3 rounded-xl transition-colors disabled:opacity-50 disabled:cursor-not-allowed flex items-center justify-center gap-2"
              >
                {submitting ? (
                  <Loader2 className="w-4 h-4 animate-spin" />
                ) : null}
                {t("common.save")}
              </FocusableButton>
              <FocusableButton
                focusKey="add-cancel"
                onEnter={onClose}
                onClick={onClose}
                data-testid="add-cancel"
                className="px-6 py-3 rounded-xl glass hover:border-primary/40 text-foreground text-sm"
              >
                {t("common.cancel")}
              </FocusableButton>
            </div>
          </FocusableSection>
          <DpadHelperOverlay show={open} id="add-server" />
        </motion.div>
      )}
    </AnimatePresence>
  );
};

const Field = ({
  focusKey,
  icon: Icon,
  placeholder,
  value,
  onChange,
  type = "text",
  testId,
  onArrowUpFocusKey,
  onArrowDownFocusKey,
}: {
  focusKey: string;
  icon: typeof User;
  placeholder: string;
  value: string;
  onChange: (v: string) => void;
  type?: "text" | "password";
  testId?: string;
  onArrowUpFocusKey?: string;
  onArrowDownFocusKey?: string;
}) => (
  <FocusableInput
    focusKey={focusKey}
    type={type}
    value={value}
    onChange={onChange}
    placeholder={placeholder}
    icon={<Icon className="w-4 h-4 text-muted-foreground shrink-0" />}
    testId={testId}
    onArrowUpFocusKey={onArrowUpFocusKey}
    onArrowDownFocusKey={onArrowDownFocusKey}
  />
);

/**
 * Format raw MAC input as `XX:XX:XX:XX:XX:XX`. Strips invalid chars, uppercases,
 * inserts `:` every 2 hex digits, caps at 12 hex digits (17 chars total).
 */
const formatMac = (raw: string): string => {
  const hex = raw.replace(/[^0-9A-Fa-f]/g, "").toUpperCase().slice(0, 12);
  return hex.match(/.{1,2}/g)?.join(":") ?? "";
};

export default AddServerDialog;
