import type { Request } from "express";
import crypto from "crypto";

export type DeviceType = "web" | "desktop" | "mobile";

export interface DeviceInfo {
  type: DeviceType;
  browser: string;
  version: string;
  os: string;
  deviceInfo: string;
}

export function detectPlatform(req: Request): DeviceType {
  const userAgent = req.headers["user-agent"] || "";
  const electronHeader = req.headers["x-electron-app"];

  if (electronHeader === "true" || userAgent.includes("Termix-Desktop")) {
    return "desktop";
  }

  if (userAgent.includes("Termix-Mobile")) {
    return "mobile";
  }

  const isDesktopOS =
    userAgent.includes("Windows") ||
    userAgent.includes("Macintosh") ||
    userAgent.includes("Mac OS X") ||
    userAgent.includes("X11") ||
    userAgent.includes("Linux x86_64");

  if (
    (userAgent.includes("Android") && !isDesktopOS) ||
    userAgent.includes("iPhone") ||
    userAgent.includes("iPad")
  ) {
    return "mobile";
  }

  return "web";
}

export function parseUserAgent(req: Request): DeviceInfo {
  const userAgent = req.headers["user-agent"] || "Unknown";
  const platform = detectPlatform(req);

  if (platform === "desktop") {
    return parseElectronUserAgent(userAgent);
  }

  if (platform === "mobile") {
    return parseMobileUserAgent(userAgent);
  }

  return parseWebUserAgent(userAgent);
}

function parseElectronUserAgent(userAgent: string): DeviceInfo {
  let os = "Unknown OS";
  let version = "Unknown";

  const termixMatch = userAgent.match(/Termix-Desktop\/([\d.]+)\s*\(([^;)]+)/);
  if (termixMatch) {
    version = termixMatch[1];
    os = termixMatch[2].trim();
  } else {
    if (userAgent.includes("Windows")) {
      os = parseWindowsVersion(userAgent);
    } else if (userAgent.includes("Mac OS X")) {
      os = parseMacVersion(userAgent);
    } else if (userAgent.includes("macOS")) {
      os = "macOS";
    } else if (userAgent.includes("Linux")) {
      os = "Linux";
    }

    const electronMatch = userAgent.match(/Electron\/([\d.]+)/);
    if (electronMatch) {
      version = electronMatch[1];
    }
  }

  return {
    type: "desktop",
    browser: "Termix Desktop",
    version,
    os,
    deviceInfo: `Termix Desktop on ${os}`,
  };
}

function parseMobileUserAgent(userAgent: string): DeviceInfo {
  let os = "Unknown OS";
  let version = "Unknown";

  const termixPlatformMatch = userAgent.match(/Termix-Mobile\/(Android|iOS)/i);
  if (termixPlatformMatch) {
    const platform = termixPlatformMatch[1];
    if (platform.toLowerCase() === "android") {
      const androidMatch = userAgent.match(/Android ([\d.]+)/);
      os = androidMatch ? `Android ${androidMatch[1]}` : "Android";
    } else if (platform.toLowerCase() === "ios") {
      const iosMatch = userAgent.match(/OS ([\d_]+)/);
      if (iosMatch) {
        const iosVersion = iosMatch[1].replace(/_/g, ".");
        os = `iOS ${iosVersion}`;
      } else {
        os = "iOS";
      }
    }
  } else {
    if (userAgent.includes("Android")) {
      const androidMatch = userAgent.match(/Android ([\d.]+)/);
      os = androidMatch ? `Android ${androidMatch[1]}` : "Android";
    } else if (
      userAgent.includes("iOS") ||
      userAgent.includes("iPhone") ||
      userAgent.includes("iPad")
    ) {
      const iosMatch = userAgent.match(/OS ([\d_]+)/);
      if (iosMatch) {
        const iosVersion = iosMatch[1].replace(/_/g, ".");
        os = `iOS ${iosVersion}`;
      } else {
        os = "iOS";
      }
    }
  }

  const versionMatch = userAgent.match(
    /Termix-Mobile\/(?:Android|iOS|)([\d.]+)/i,
  );
  if (versionMatch) {
    version = versionMatch[1];
  }

  return {
    type: "mobile",
    browser: "Termix Mobile",
    version,
    os,
    deviceInfo: `Termix Mobile on ${os}`,
  };
}

function parseWebUserAgent(userAgent: string): DeviceInfo {
  let browser = "Unknown Browser";
  let version = "Unknown";
  let os = "Unknown OS";

  if (userAgent.includes("Edg/")) {
    const match = userAgent.match(/Edg\/([\d.]+)/);
    browser = "Edge";
    version = match ? match[1] : "Unknown";
  } else if (userAgent.includes("Chrome/") && !userAgent.includes("Edg")) {
    const match = userAgent.match(/Chrome\/([\d.]+)/);
    browser = "Chrome";
    version = match ? match[1] : "Unknown";
  } else if (userAgent.includes("Firefox/")) {
    const match = userAgent.match(/Firefox\/([\d.]+)/);
    browser = "Firefox";
    version = match ? match[1] : "Unknown";
  } else if (userAgent.includes("Safari/") && !userAgent.includes("Chrome")) {
    const match = userAgent.match(/Version\/([\d.]+)/);
    browser = "Safari";
    version = match ? match[1] : "Unknown";
  } else if (userAgent.includes("Opera/") || userAgent.includes("OPR/")) {
    const match = userAgent.match(/(?:Opera|OPR)\/([\d.]+)/);
    browser = "Opera";
    version = match ? match[1] : "Unknown";
  }

  if (userAgent.includes("Windows")) {
    os = parseWindowsVersion(userAgent);
  } else if (userAgent.includes("Android")) {
    const match = userAgent.match(/Android ([\d.]+)/);
    os = match ? `Android ${match[1]}` : "Android";
  } else if (
    userAgent.includes("iOS") ||
    userAgent.includes("iPhone") ||
    userAgent.includes("iPad")
  ) {
    const match = userAgent.match(/OS ([\d_]+)/);
    if (match) {
      const iosVersion = match[1].replace(/_/g, ".");
      os = `iOS ${iosVersion}`;
    } else {
      os = "iOS";
    }
  } else if (userAgent.includes("Mac OS X")) {
    os = parseMacVersion(userAgent);
  } else if (userAgent.includes("Linux")) {
    os = "Linux";
  }

  if (version !== "Unknown") {
    const versionParts = version.split(".");
    version = versionParts.slice(0, 2).join(".");
  }

  return {
    type: "web",
    browser,
    version,
    os,
    deviceInfo: `${browser} ${version} on ${os}`,
  };
}

function parseWindowsVersion(userAgent: string): string {
  if (userAgent.includes("Windows NT 10.0")) {
    return "Windows 10/11";
  } else if (userAgent.includes("Windows NT 6.3")) {
    return "Windows 8.1";
  } else if (userAgent.includes("Windows NT 6.2")) {
    return "Windows 8";
  } else if (userAgent.includes("Windows NT 6.1")) {
    return "Windows 7";
  } else if (userAgent.includes("Windows NT 6.0")) {
    return "Windows Vista";
  } else if (
    userAgent.includes("Windows NT 5.1") ||
    userAgent.includes("Windows NT 5.2")
  ) {
    return "Windows XP";
  }
  return "Windows";
}

function parseMacVersion(userAgent: string): string {
  const match = userAgent.match(/Mac OS X ([\d_]+)/);
  if (match) {
    const version = match[1].replace(/_/g, ".");
    const parts = version.split(".");
    const major = parseInt(parts[0]);
    const minor = parseInt(parts[1]);

    if (major === 10) {
      if (minor >= 15) return `macOS ${major}.${minor}`;
      if (minor === 14) return "macOS Mojave";
      if (minor === 13) return "macOS High Sierra";
      if (minor === 12) return "macOS Sierra";
    } else if (major >= 11) {
      return `macOS ${major}`;
    }

    return `macOS ${version}`;
  }
  return "macOS";
}

/** Return the installation-scoped identifier used for trusted-device checks. */
export function getDeviceId(req: Request): string | null {
  const value = req.headers["x-termix-device-id"];
  if (typeof value !== "string" || !/^[a-f0-9]{64}$/.test(value)) return null;
  return value;
}

/** Bind a trusted-device record to one client installation and platform. */
export function generateDeviceFingerprint(
  deviceInfo: DeviceInfo,
  deviceId: string | null,
): string | null {
  if (!deviceId) return null;
  return crypto
    .createHash("sha256")
    .update(`${deviceInfo.type}|${deviceId}`)
    .digest("hex");
}
