/**
 * Zero-dependency User-Agent parser.
 *
 * Good enough for a security/audit log (device type, browser, OS). It never
 * throws — worst case it returns 'unknown'. If you later want richer data
 * (device model, exact engine), install `ua-parser-js` and swap parseUserAgent
 * to use it; the ClientLoginLog columns already fit that shape.
 *
 *   npm i ua-parser-js
 *   import { UAParser } from 'ua-parser-js';
 *   const r = new UAParser(ua).getResult();
 *   -> { browser:{name,version}, os:{name,version}, device:{type} }
 */

export interface ParsedUA {
  device_type: 'mobile' | 'tablet' | 'desktop' | 'bot' | 'unknown';
  browser: string | null;
  browser_version: string | null;
  os: string | null;
  os_version: string | null;
}

function firstMatch(ua: string, re: RegExp): string | null {
  const m = ua.match(re);
  return m && m[1] ? m[1] : null;
}

export function parseUserAgent(uaRaw: string | undefined | null): ParsedUA {
  const out: ParsedUA = {
    device_type: 'unknown',
    browser: null,
    browser_version: null,
    os: null,
    os_version: null,
  };
  if (!uaRaw || typeof uaRaw !== 'string') return out;

  const ua = uaRaw.slice(0, 1024); // hard cap, defensive
  const lc = ua.toLowerCase();

  // ── Bots / crawlers first ────────────────────────────────────
  if (/bot|crawl|spider|slurp|curl|wget|python-requests|postman|axios|node-fetch|httpclient|headless/i.test(ua)) {
    out.device_type = 'bot';
  }

  // ── OS ───────────────────────────────────────────────────────
  if (/windows nt/i.test(ua)) {
    out.os = 'Windows';
    const v = firstMatch(ua, /windows nt ([0-9.]+)/i);
    const map: Record<string, string> = {
      '10.0': '10/11',
      '6.3': '8.1',
      '6.2': '8',
      '6.1': '7',
    };
    out.os_version = (v && map[v]) || v || null;
  } else if (/iphone|ipad|ipod/i.test(ua)) {
    out.os = 'iOS';
    out.os_version = (firstMatch(ua, /os ([0-9_]+)/i) || '').replace(/_/g, '.') || null;
  } else if (/mac os x/i.test(ua)) {
    out.os = 'macOS';
    out.os_version = (firstMatch(ua, /mac os x ([0-9_]+)/i) || '').replace(/_/g, '.') || null;
  } else if (/android/i.test(ua)) {
    out.os = 'Android';
    out.os_version = firstMatch(ua, /android ([0-9.]+)/i);
  } else if (/linux/i.test(ua)) {
    out.os = 'Linux';
  } else if (/cros/i.test(ua)) {
    out.os = 'ChromeOS';
  }

  // ── Device type (if not already a bot) ───────────────────────
  if (out.device_type !== 'bot') {
    if (/ipad|tablet|playbook|silk|(android(?!.*mobile))/i.test(ua)) {
      out.device_type = 'tablet';
    } else if (/mobi|iphone|ipod|android.*mobile|windows phone|blackberry|bb10|opera mini|iemobile/i.test(lc)) {
      out.device_type = 'mobile';
    } else if (out.os) {
      out.device_type = 'desktop';
    }
  }

  // ── Browser (order matters: check derivatives before Chrome/Safari) ──
  const detect: Array<[RegExp, string]> = [
    [/edg(?:a|ios)?\/([0-9.]+)/i, 'Edge'],
    [/opr\/([0-9.]+)/i, 'Opera'],
    [/opera[ /]([0-9.]+)/i, 'Opera'],
    [/samsungbrowser\/([0-9.]+)/i, 'Samsung Internet'],
    [/firefox\/([0-9.]+)/i, 'Firefox'],
    [/fxios\/([0-9.]+)/i, 'Firefox'],
    [/crios\/([0-9.]+)/i, 'Chrome'],
    [/chrome\/([0-9.]+)/i, 'Chrome'],
    [/version\/([0-9.]+).*safari/i, 'Safari'],
    [/msie ([0-9.]+)/i, 'Internet Explorer'],
    [/trident.*rv:([0-9.]+)/i, 'Internet Explorer'],
  ];
  for (const [re, name] of detect) {
    const v = firstMatch(ua, re);
    if (v) {
      out.browser = name;
      out.browser_version = v;
      break;
    }
  }
  if (!out.browser && /safari/i.test(ua)) out.browser = 'Safari';

  return out;
}
