const DEVICE_ID_KEY = "fpsms_device_id";
const DISPLAY_NAME_KEY = "fpsms_device_display_name";

/** Chromium User-Agent Client Hints (not in lib.dom Navigator yet). */
interface NavigatorUAData {
  mobile?: boolean;
  platform?: string;
}

interface NavigatorWithUAData extends Navigator {
  readonly userAgentData?: NavigatorUAData;
}

export function getOrCreateDeviceId(): string {
  if (typeof window === "undefined") return "";
  let id = localStorage.getItem(DEVICE_ID_KEY);
  if (!id) {
    id =
      typeof crypto !== "undefined" && crypto.randomUUID
        ? crypto.randomUUID()
        : `dev-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
    localStorage.setItem(DEVICE_ID_KEY, id);
  }
  return id;
}

export function getDeviceDisplayName(): string {
  if (typeof window === "undefined") return "";
  return localStorage.getItem(DISPLAY_NAME_KEY)?.trim() ?? "";
}

export function setDeviceDisplayName(name: string): void {
  if (typeof window === "undefined") return;
  const trimmed = name.trim();
  if (trimmed) {
    localStorage.setItem(DISPLAY_NAME_KEY, trimmed.slice(0, 128));
  } else {
    localStorage.removeItem(DISPLAY_NAME_KEY);
  }
}

function screenShortSidePx(): number {
  if (typeof window === "undefined") return 0;
  return Math.min(window.screen.width, window.screen.height);
}

/**
 * Classify device for presence monitoring.
 * iPadOS 13+ often sends a desktop Macintosh UA; use touch + platform heuristics.
 */
/** Display IP; loopback / same-machine traffic shows as "Server". */
export function formatClientIpDisplay(ip?: string | null): string {
  if (!ip?.trim()) return "—";
  const n = ip.trim().toLowerCase();
  if (n === "server") return "Server";
  if (n === "127.0.0.1" || n === "localhost" || n === "::1" || n === "0:0:0:0:0:0:0:1") {
    return "Server";
  }
  if (n.startsWith("127.")) return "Server";
  if (n.includes(":") && n.replace(/:/g, "").replace(/0/g, "") === "") return "Server";
  return ip.trim();
}

/** CSS px; tablets in portrait are often 600–800; phones are usually smaller. */
const TABLET_MIN_SHORT_SIDE_PX = 480;

function hasTouchCapability(): boolean {
  if (typeof navigator === "undefined") return false;
  const touchPoints = navigator.maxTouchPoints ?? 0;
  return touchPoints > 0 || "ontouchstart" in window;
}

export function detectClientTypeFromUa(): string {
  if (typeof navigator === "undefined") return "unknown";

  const ua = navigator.userAgent.toLowerCase();
  const touchPoints = navigator.maxTouchPoints ?? 0;
  const hasTouch = hasTouchCapability();
  const shortSide = screenShortSidePx();

  if (ua.includes("iphone") || ua.includes("ipod")) {
    return "mobile";
  }

  if (ua.includes("ipad") || ua.includes("tablet")) {
    return "tablet";
  }

  // iPadOS 13+ "desktop" Safari: MacIntel + multi-touch, no "iPad" in UA string
  if (
    (navigator.platform === "MacIntel" || ua.includes("macintosh")) &&
    touchPoints > 1
  ) {
    return "tablet";
  }

  // User-Agent Client Hints (Chromium)
  const uad = (navigator as NavigatorWithUAData).userAgentData;
  if (uad) {
    const platform = uad.platform?.toLowerCase() ?? "";
    if (platform.includes("android")) {
      if (!uad.mobile) return "tablet";
      if (hasTouch && shortSide >= TABLET_MIN_SHORT_SIDE_PX) return "tablet";
      return "mobile";
    }
    if (platform === "ios" && hasTouch) {
      return "tablet";
    }
  }

  if (ua.includes("android")) {
    // Warehouse slates almost always include "Mobile" in UA even when not phones
    if (!ua.includes("mobile")) return "tablet";
    if (hasTouch && shortSide >= TABLET_MIN_SHORT_SIDE_PX) return "tablet";
    // Small Android phone
    if (shortSide > 0 && shortSide < 400) return "mobile";
    return "tablet";
  }

  if (ua.includes("mobile")) {
    return "mobile";
  }

  // Touch slate / Surface / kiosk with desktop-like UA
  if (hasTouch && shortSide >= 400) {
    return "tablet";
  }

  return "desktop";
}
