#!/usr/bin/env python3
"""Build SQLite data databases for SystemMonitor.

Creates:
  - innocuous_macs.db  : Consumer device MAC profiles for stealth spoofing
  - oui.db             : IEEE OUI vendor lookup (schema only, populated at first run)
  - os_sigs.db         : Passive OS fingerprint signatures (schema only)
  - dhcp_fingerprints.db : DHCP option 55 fingerprints (schema only)
  - ja3_fingerprints.db  : JA3 TLS client fingerprints (schema only)

Called by setup.sh during bootstrap.
"""

import argparse
import os
import sqlite3
import sys
from pathlib import Path


def create_innocuous_macs_db(db_path: str) -> None:
    """Create innocuous MAC profiles database with ~50 real device profiles.

    Each profile includes OUI, vendor, device_name, DHCP hostname pattern,
    DHCP vendor class, TTL, TCP window size, and OS family -- everything
    needed to impersonate the device at the network fingerprint level.

    Table name and column names match what mac_manager.py queries:
      mac_profiles(device_type, device_name, vendor, oui, ...)
    """
    conn = sqlite3.connect(db_path)
    conn.execute("PRAGMA journal_mode=WAL")
    conn.executescript("""
        CREATE TABLE IF NOT EXISTS mac_profiles (
            id              INTEGER PRIMARY KEY AUTOINCREMENT,
            device_type     TEXT NOT NULL,
            oui             TEXT NOT NULL,
            vendor          TEXT NOT NULL,
            device_name     TEXT NOT NULL,
            dhcp_hostname   TEXT,
            dhcp_vendor_class TEXT,
            ttl             INTEGER DEFAULT 64,
            tcp_window      INTEGER DEFAULT 65535,
            os_family       TEXT DEFAULT 'Linux'
        );

        CREATE INDEX IF NOT EXISTS idx_mac_profiles_type ON mac_profiles(device_type);
        CREATE INDEX IF NOT EXISTS idx_mac_profiles_oui ON mac_profiles(oui);
    """)

    profiles = [
        # ── Streaming devices ───────────────────────────────────────────
        ("streaming", "FC:65:DE", "Amazon", "Fire TV Stick 4K",
         "amazon-", "AmazonFireTV", 64, 26883, "Android"),
        ("streaming", "A0:02:DC", "Amazon", "Fire TV Stick Lite",
         "amazon-", "AmazonFireTV", 64, 26883, "Android"),
        ("streaming", "44:D5:F2", "Amazon", "Fire TV Cube",
         "amazon-", "AmazonFireTV", 64, 26883, "Android"),
        ("streaming", "34:D2:70", "Amazon", "Fire TV Stick 4K Max",
         "amazon-", "AmazonFireTV", 64, 26883, "Android"),
        ("streaming", "D8:31:34", "Roku", "Roku Ultra",
         "Roku-", "Roku/DVP-12.0", 64, 65535, "Linux"),
        ("streaming", "B0:A7:37", "Roku", "Roku Express",
         "Roku-", "Roku/DVP-10.0", 64, 65535, "Linux"),
        ("streaming", "10:59:32", "Roku", "Roku Streaming Stick 4K",
         "Roku-", "Roku/DVP-13.0", 64, 65535, "Linux"),
        ("streaming", "CC:6D:A0", "Roku", "Roku Express 4K",
         "Roku-", "Roku/DVP-11.0", 64, 65535, "Linux"),
        ("streaming", "54:60:09", "Google", "Chromecast",
         "Chromecast-", "Google", 64, 65535, "Linux"),
        ("streaming", "F4:F5:D8", "Google", "Chromecast with Google TV",
         "Chromecast-", "Google", 64, 65535, "Android"),
        ("streaming", "48:D6:D5", "Google", "Chromecast with Google TV 4K",
         "Chromecast-", "Google", 64, 65535, "Android"),
        ("streaming", "A4:83:E7", "Apple", "Apple TV 4K",
         "Apple-TV", "AAPLBK", 64, 65535, "tvOS"),
        ("streaming", "40:CB:C0", "Apple", "Apple TV HD",
         "Apple-TV", "AAPLBK", 64, 65535, "tvOS"),
        ("streaming", "00:04:4B", "Nvidia", "Nvidia Shield TV Pro",
         "SHIELD-", "NVIDIA", 64, 65535, "Android"),
        ("streaming", "48:B0:2D", "Nvidia", "Nvidia Shield TV",
         "SHIELD-", "NVIDIA", 64, 65535, "Android"),

        # ── Smart TVs ──────────────────────────────────────────────────
        ("smart_tv", "8C:79:F5", "Samsung", "Samsung Smart TV",
         "Samsung-TV", "Samsung", 128, 65535, "Tizen"),
        ("smart_tv", "BC:14:EF", "Samsung", "Samsung QLED TV",
         "Samsung-TV", "Samsung", 128, 65535, "Tizen"),
        ("smart_tv", "F0:6E:0B", "Samsung", "Samsung Frame TV",
         "Samsung-TV", "Samsung", 128, 65535, "Tizen"),
        ("smart_tv", "A8:23:FE", "LG", "LG webOS TV",
         "LG-TV", "LG", 64, 65535, "webOS"),
        ("smart_tv", "58:FD:B1", "LG", "LG OLED TV",
         "LG-TV", "LG", 64, 65535, "webOS"),
        ("smart_tv", "38:8C:50", "LG", "LG NanoCell TV",
         "LG-TV", "LG", 64, 65535, "webOS"),
        ("smart_tv", "D4:38:9C", "Vizio", "Vizio SmartCast TV",
         "VIZIO-TV", "Vizio", 64, 65535, "Linux"),
        ("smart_tv", "C0:79:82", "TCL", "TCL Roku TV",
         "TCL-TV", "Roku/DVP", 64, 65535, "Linux"),
        ("smart_tv", "C8:02:10", "Sony", "Sony Bravia Android TV",
         "Sony-TV", "Sony", 64, 65535, "Android"),
        ("smart_tv", "04:95:E6", "Hisense", "Hisense Vidaa TV",
         "Hisense-TV", "Hisense", 64, 65535, "Linux"),
        ("smart_tv", "E4:B3:18", "Insignia", "Insignia Fire TV",
         "amazon-", "AmazonFireTV", 64, 26883, "Android"),
        ("smart_tv", "7C:2A:DB", "Philips", "Philips Android TV",
         "Philips-TV", "Philips", 64, 65535, "Android"),
        ("smart_tv", "E0:91:53", "Toshiba", "Toshiba Fire TV",
         "amazon-", "AmazonFireTV", 64, 26883, "Android"),

        # ── Smart speakers / assistants ────────────────────────────────
        ("smart_speaker", "48:A6:B8", "Sonos", "Sonos One",
         "Sonos-", "Sonos", 64, 65535, "Linux"),
        ("smart_speaker", "5C:AA:FD", "Sonos", "Sonos Beam",
         "Sonos-", "Sonos", 64, 65535, "Linux"),
        ("smart_speaker", "78:28:CA", "Sonos", "Sonos Move",
         "Sonos-", "Sonos", 64, 65535, "Linux"),
        ("smart_speaker", "B8:E9:37", "Sonos", "Sonos Era 100",
         "Sonos-", "Sonos", 64, 65535, "Linux"),
        ("smart_speaker", "30:FD:38", "Google", "Google Home Mini",
         "Google-Home-", "Google", 64, 65535, "Linux"),
        ("smart_speaker", "1C:F2:9A", "Google", "Google Nest Hub",
         "Google-Nest-", "Google", 64, 65535, "Linux"),
        ("smart_speaker", "20:DF:B9", "Google", "Google Nest Mini",
         "Google-Nest-", "Google", 64, 65535, "Linux"),
        ("smart_speaker", "F8:0F:F9", "Google", "Google Nest Audio",
         "Google-Nest-", "Google", 64, 65535, "Linux"),
        ("smart_speaker", "68:54:FD", "Amazon", "Echo Dot",
         "amazon-", "AmazonEcho", 64, 26883, "Android"),
        ("smart_speaker", "74:C2:46", "Amazon", "Echo Show",
         "amazon-", "AmazonEcho", 64, 26883, "Android"),
        ("smart_speaker", "F0:81:73", "Amazon", "Echo Pop",
         "amazon-", "AmazonEcho", 64, 26883, "Android"),
        ("smart_speaker", "38:F7:3D", "Amazon", "Echo Studio",
         "amazon-", "AmazonEcho", 64, 26883, "Android"),
        ("smart_speaker", "AC:63:BE", "Apple", "HomePod Mini",
         "HomePod-", "Apple", 64, 65535, "audioOS"),
        ("smart_speaker", "28:6D:97", "Apple", "HomePod",
         "HomePod-", "Apple", 64, 65535, "audioOS"),
        ("smart_speaker", "30:21:3B", "Bose", "Bose SoundLink",
         "Bose-", "Bose", 64, 65535, "Linux"),
        ("smart_speaker", "04:52:C7", "Bose", "Bose Home Speaker 500",
         "Bose-", "Bose", 64, 65535, "Linux"),

        # ── Smart home / IoT ──────────────────────────────────────────
        ("iot", "4C:EB:D6", "Amazon", "Ring Doorbell",
         "Ring-", "Amazon", 64, 65535, "Linux"),
        ("iot", "6C:63:9C", "Amazon", "Ring Spotlight Cam",
         "Ring-", "Amazon", 64, 65535, "Linux"),
        ("iot", "18:B4:30", "Nest", "Nest Thermostat",
         "Nest-", "Nest", 64, 65535, "Linux"),
        ("iot", "64:16:66", "Nest", "Nest Protect",
         "Nest-", "Nest", 64, 65535, "Linux"),
        ("iot", "18:B4:30", "Nest", "Nest Cam Indoor",
         "Nest-", "Nest", 64, 65535, "Linux"),
        ("iot", "00:17:88", "Philips", "Philips Hue Bridge",
         "Philips-hue", "Philips-hue", 64, 65535, "Linux"),
        ("iot", "D8:0D:17", "TP-Link", "TP-Link Kasa Smart Plug",
         "TP-Link-", "TP-Link", 64, 65535, "Linux"),
        ("iot", "B0:95:75", "TP-Link", "TP-Link Tapo Camera",
         "Tapo-", "TP-Link", 64, 65535, "Linux"),
        ("iot", "2C:AA:8E", "Wyze", "Wyze Cam v3",
         "Wyze-", "Wyze", 64, 65535, "Linux"),
        ("iot", "A4:DA:22", "Wyze", "Wyze Cam Outdoor",
         "Wyze-", "Wyze", 64, 65535, "Linux"),
        ("iot", "44:61:32", "Ecobee", "Ecobee Thermostat",
         "ecobee-", "ecobee", 64, 65535, "Linux"),
        ("iot", "50:14:79", "iRobot", "Roomba i7",
         "iRobot-", "iRobot", 64, 65535, "Linux"),
        ("iot", "24:E1:24", "iRobot", "Roomba j7",
         "iRobot-", "iRobot", 64, 65535, "Linux"),
        ("iot", "DC:A6:32", "Raspberry Pi", "IoT Sensor",
         "raspberrypi", "RaspberryPi", 64, 29200, "Linux"),
        ("iot", "B4:E6:2D", "Raspberry Pi", "IoT Gateway",
         "raspberrypi", "RaspberryPi", 64, 29200, "Linux"),
        ("iot", "B8:27:EB", "Raspberry Pi", "IoT Controller",
         "raspberrypi", "RaspberryPi", 64, 29200, "Linux"),
        ("iot", "2C:F4:32", "Raspberry Pi", "Raspberry Pi 5",
         "raspberrypi", "RaspberryPi", 64, 29200, "Linux"),
        ("iot", "98:CD:AC", "SimpliSafe", "SimpliSafe Hub",
         "SimpliSafe-", "SimpliSafe", 64, 65535, "Linux"),
        ("iot", "CC:DB:A7", "Arlo", "Arlo Pro 4",
         "Arlo-", "Arlo", 64, 65535, "Linux"),
        ("iot", "9C:21:6A", "TP-Link", "TP-Link Kasa Smart Switch",
         "TP-Link-", "TP-Link", 64, 65535, "Linux"),
        ("iot", "78:11:DC", "Xiaomi", "Xiaomi Mi Smart Sensor",
         "Xiaomi-", "Xiaomi", 64, 65535, "Linux"),
        ("iot", "04:CF:8C", "Xiaomi", "Xiaomi Roborock",
         "Roborock-", "Xiaomi", 64, 65535, "Linux"),
        ("iot", "50:C7:BF", "TP-Link", "TP-Link Kasa Cam",
         "Kasa-", "TP-Link", 64, 65535, "Linux"),
        ("iot", "B0:BE:76", "Eufy", "Eufy Doorbell",
         "eufy-", "Anker", 64, 65535, "Linux"),
        ("iot", "58:D5:6E", "Wemo", "Wemo Smart Plug",
         "Wemo-", "Belkin", 64, 65535, "Linux"),
        ("iot", "94:10:3E", "Belkin", "Belkin WeMo Switch",
         "Wemo-", "Belkin", 64, 65535, "Linux"),
        ("iot", "38:2B:78", "Chamberlain", "myQ Smart Garage",
         "myQ-", "Chamberlain", 64, 65535, "Linux"),
        ("iot", "00:1A:22", "Lutron", "Lutron Caseta Bridge",
         "Lutron-", "Lutron", 64, 65535, "Linux"),
        ("iot", "D0:73:D5", "Lifx", "Lifx Smart Bulb",
         "LIFX-", "LIFX", 64, 65535, "Linux"),
        ("iot", "7C:64:56", "Samsung", "SmartThings Hub",
         "SmartThings-", "Samsung", 64, 65535, "Linux"),
        ("iot", "68:DB:F5", "August", "August Smart Lock",
         "August-", "August", 64, 65535, "Linux"),
        ("iot", "B0:CE:18", "Honeywell", "Honeywell T6 Thermostat",
         "Honeywell-", "Honeywell", 64, 65535, "Linux"),

        # ── Printers ──────────────────────────────────────────────────
        ("printer", "3C:D9:2B", "HP", "HP LaserJet Pro",
         "HP", "Hewlett-Packard", 128, 8192, "HP JetDirect"),
        ("printer", "C8:B5:B7", "HP", "HP OfficeJet Pro",
         "HP", "Hewlett-Packard", 128, 8192, "HP JetDirect"),
        ("printer", "94:57:A5", "HP", "HP Color LaserJet",
         "HP", "Hewlett-Packard", 128, 8192, "HP JetDirect"),
        ("printer", "D0:BF:9C", "HP", "HP ENVY Pro",
         "HP", "Hewlett-Packard", 128, 8192, "HP JetDirect"),
        ("printer", "30:05:5C", "Brother", "Brother HL-L2350DW",
         "BRN", "Brother", 128, 8192, "Brother"),
        ("printer", "00:80:77", "Brother", "Brother MFC-L2750DW",
         "BRN", "Brother", 128, 8192, "Brother"),
        ("printer", "00:1B:A9", "Brother", "Brother DCP-L2550DW",
         "BRN", "Brother", 128, 8192, "Brother"),
        ("printer", "2C:F0:5D", "Epson", "Epson EcoTank ET-4760",
         "EPSON", "EPSON", 128, 8192, "Epson"),
        ("printer", "00:26:AB", "Epson", "Epson WorkForce Pro",
         "EPSON", "EPSON", 128, 8192, "Epson"),
        ("printer", "64:EB:8C", "Canon", "Canon PIXMA G6020",
         "Canon", "Canon", 128, 8192, "Canon"),
        ("printer", "18:0C:AC", "Canon", "Canon imageCLASS",
         "Canon", "Canon", 128, 8192, "Canon"),
        ("printer", "00:C0:EE", "Kyocera", "Kyocera ECOSYS P2235dn",
         "KYOCERA", "KYOCERA", 128, 8192, "Kyocera"),
        ("printer", "00:21:B7", "Lexmark", "Lexmark MS431dn",
         "Lexmark-", "Lexmark", 128, 8192, "Lexmark"),
        ("printer", "00:00:74", "Ricoh", "Ricoh SP C261SFNw",
         "Ricoh-", "RICOH", 128, 8192, "Ricoh"),
        ("printer", "00:00:AA", "Xerox", "Xerox VersaLink C400",
         "Xerox-", "XEROX", 128, 8192, "Xerox"),

        # ── Gaming consoles ───────────────────────────────────────────
        ("gaming", "7C:ED:8D", "Microsoft", "Xbox Series X",
         "Xbox-", "Microsoft", 128, 65535, "Windows"),
        ("gaming", "C8:3F:26", "Microsoft", "Xbox Series S",
         "Xbox-", "Microsoft", 128, 65535, "Windows"),
        ("gaming", "00:D9:D1", "Sony", "PlayStation 5",
         "PS5-", "Sony", 64, 65535, "FreeBSD"),
        ("gaming", "98:B6:E9", "Sony", "PlayStation 4",
         "PS4-", "Sony", 64, 65535, "FreeBSD"),
        ("gaming", "7C:BB:8A", "Nintendo", "Nintendo Switch",
         "Nintendo-", "Nintendo", 64, 65535, "Nintendo"),
        ("gaming", "58:2F:40", "Nintendo", "Nintendo Switch OLED",
         "Nintendo-", "Nintendo", 64, 65535, "Nintendo"),
        ("gaming", "34:AF:B3", "Valve", "Steam Deck",
         "steamdeck-", "Valve", 64, 29200, "Linux"),

        # ── Phones / tablets ──────────────────────────────────────────
        ("phone", "A4:83:E7", "Apple", "iPhone 15 Pro",
         "iphone", "dhcpcd-6.x.x", 64, 65535, "iOS"),
        ("phone", "40:CB:C0", "Apple", "iPad Air",
         "ipad", "dhcpcd-6.x.x", 64, 65535, "iPadOS"),
        ("phone", "3C:06:30", "Apple", "iPhone 14",
         "iphone", "dhcpcd-6.x.x", 64, 65535, "iOS"),
        ("phone", "48:A9:1C", "Apple", "iPhone 13",
         "iphone", "dhcpcd-6.x.x", 64, 65535, "iOS"),
        ("tablet", "3C:28:6D", "Samsung", "Galaxy Tab S9",
         "Samsung-Tab", "dhcpcd-6.x.x", 64, 65535, "Android"),
        ("phone", "DC:1A:C5", "Samsung", "Galaxy S24",
         "Galaxy-S", "dhcpcd-6.x.x", 64, 65535, "Android"),
        ("phone", "84:25:19", "Samsung", "Galaxy S23",
         "Galaxy-S", "dhcpcd-6.x.x", 64, 65535, "Android"),
        ("phone", "50:55:27", "Google", "Pixel 8 Pro",
         "Pixel-", "dhcpcd-6.x.x", 64, 65535, "Android"),
        ("phone", "94:B8:6D", "Google", "Pixel 7",
         "Pixel-", "dhcpcd-6.x.x", 64, 65535, "Android"),
        ("phone", "4C:4F:EE", "OnePlus", "OnePlus 12",
         "OnePlus-", "dhcpcd-6.x.x", 64, 65535, "Android"),
        ("phone", "9C:2E:A1", "Xiaomi", "Xiaomi 14",
         "Xiaomi-", "dhcpcd-6.x.x", 64, 65535, "Android"),
        ("tablet", "64:A2:F9", "Apple", "iPad Pro M2",
         "ipad", "dhcpcd-6.x.x", 64, 65535, "iPadOS"),

        # ── Wearables ─────────────────────────────────────────────────
        ("wearable", "38:EC:0D", "Apple", "Apple Watch Ultra",
         "Apple-Watch", "Apple", 64, 65535, "watchOS"),
        ("wearable", "44:00:49", "Apple", "Apple Watch SE",
         "Apple-Watch", "Apple", 64, 65535, "watchOS"),
        ("wearable", "C8:28:E5", "Fitbit", "Fitbit Sense 2",
         "Fitbit-", "Fitbit", 64, 65535, "FitbitOS"),
        ("wearable", "E0:E0:FC", "Garmin", "Garmin Venu 3",
         "Garmin-", "Garmin", 64, 65535, "Linux"),
        ("wearable", "CC:79:CF", "Samsung", "Galaxy Watch 6",
         "Galaxy-Watch", "Samsung", 64, 65535, "Tizen"),

        # ── Network gear (hide as infrastructure) ─────────────────────
        ("network", "B4:FB:E4", "Ubiquiti", "UniFi AP",
         "UAP-", "Ubiquiti", 64, 65535, "Linux"),
        ("network", "78:8A:20", "Ubiquiti", "USG Gateway",
         "USG-", "Ubiquiti", 64, 65535, "Linux"),
        ("network", "24:5A:4C", "Ubiquiti", "UniFi Switch",
         "USW-", "Ubiquiti", 64, 65535, "Linux"),
        ("network", "14:CC:20", "TP-Link", "TP-Link Archer AX50",
         "TL-", "TP-Link", 64, 65535, "Linux"),
        ("network", "AC:84:C6", "TP-Link", "TP-Link Deco M5",
         "Deco-", "TP-Link", 64, 65535, "Linux"),
        ("network", "20:A6:CD", "Netgear", "Netgear Orbi",
         "Orbi-", "Netgear", 64, 65535, "Linux"),
        ("network", "C4:04:15", "Netgear", "Netgear Nighthawk",
         "NETGEAR-", "Netgear", 64, 65535, "Linux"),
        ("network", "60:38:E0", "Linksys", "Linksys Velop",
         "Linksys-", "Linksys", 64, 65535, "Linux"),
        ("network", "04:D4:C4", "ASUS", "ASUS RT-AX86U",
         "ASUS-RT-", "ASUS", 64, 65535, "Linux"),
        ("network", "F8:BB:BF", "eero", "eero Pro 6E",
         "eero-", "eero", 64, 65535, "Linux"),
        ("network", "68:D7:9A", "eero", "eero 6+",
         "eero-", "eero", 64, 65535, "Linux"),
        ("network", "74:DA:88", "TP-Link", "TP-Link Deco XE75",
         "Deco-", "TP-Link", 64, 65535, "Linux"),
        ("network", "AC:9E:17", "ASUS", "ASUS ZenWiFi",
         "ASUS-", "ASUS", 64, 65535, "Linux"),

        # ── NAS / home servers ────────────────────────────────────────
        ("nas", "00:11:32", "Synology", "Synology DS920+",
         "DiskStation-", "Synology", 64, 29200, "Linux"),
        ("nas", "00:11:32", "Synology", "Synology DS423",
         "DiskStation-", "Synology", 64, 29200, "Linux"),
        ("nas", "24:5E:BE", "QNAP", "QNAP TS-464",
         "QNAP-", "QNAP", 64, 29200, "Linux"),
        ("nas", "00:08:9B", "QNAP", "QNAP TS-253E",
         "QNAP-", "QNAP", 64, 29200, "Linux"),
    ]

    conn.executemany("""
        INSERT OR IGNORE INTO mac_profiles (device_type, oui, vendor, device_name,
                                            dhcp_hostname, dhcp_vendor_class,
                                            ttl, tcp_window, os_family)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
    """, profiles)

    conn.commit()
    count = conn.execute("SELECT COUNT(*) FROM mac_profiles").fetchone()[0]
    conn.close()
    print(f"  innocuous_macs.db: {count} device profiles")


def create_oui_db(db_path: str) -> None:
    """Create OUI database schema (populated from IEEE list at first run)."""
    conn = sqlite3.connect(db_path)
    conn.execute("PRAGMA journal_mode=WAL")
    conn.executescript("""
        CREATE TABLE IF NOT EXISTS oui (
            prefix  TEXT PRIMARY KEY,
            vendor  TEXT NOT NULL
        );

        CREATE INDEX IF NOT EXISTS idx_oui_vendor ON oui(vendor);
    """)

    # Seed with common OUIs used by profiles to ensure basic functionality
    # before the full IEEE list is downloaded
    seed_ouis = [
        ("FC:65:DE", "Amazon Technologies Inc."),
        ("A0:02:DC", "Amazon Technologies Inc."),
        ("44:D5:F2", "Amazon Technologies Inc."),
        ("D8:31:34", "Roku, Inc."),
        ("B0:A7:37", "Roku, Inc."),
        ("54:60:09", "Google, Inc."),
        ("F4:F5:D8", "Google, Inc."),
        ("A4:83:E7", "Apple, Inc."),
        ("40:CB:C0", "Apple, Inc."),
        ("8C:79:F5", "Samsung Electronics Co.,Ltd"),
        ("BC:14:EF", "Samsung Electronics Co.,Ltd"),
        ("A8:23:FE", "LG Electronics"),
        ("58:FD:B1", "LG Electronics"),
        ("D4:38:9C", "Vizio, Inc."),
        ("C0:79:82", "TCL King Electrical Appliances"),
        ("C8:02:10", "Sony Interactive Entertainment Inc."),
        ("48:A6:B8", "Sonos, Inc."),
        ("5C:AA:FD", "Sonos, Inc."),
        ("30:FD:38", "Google, Inc."),
        ("1C:F2:9A", "Google, Inc."),
        ("68:54:FD", "Amazon Technologies Inc."),
        ("74:C2:46", "Amazon Technologies Inc."),
        ("4C:EB:D6", "Amazon Technologies Inc."),
        ("18:B4:30", "Nest Labs Inc."),
        ("00:17:88", "Philips Lighting BV"),
        ("D8:0D:17", "TP-Link Technologies Co.,Ltd."),
        ("2C:AA:8E", "Wyze Labs Inc."),
        ("44:61:32", "ecobee inc."),
        ("50:14:79", "iRobot Corporation"),
        ("24:E1:24", "iRobot Corporation"),
        ("DC:A6:32", "Raspberry Pi Trading Ltd"),
        ("B4:E6:2D", "Raspberry Pi Trading Ltd"),
        ("B8:27:EB", "Raspberry Pi Foundation"),
        ("3C:D9:2B", "HP Inc."),
        ("C8:B5:B7", "HP Inc."),
        ("30:05:5C", "Brother Industries, LTD."),
        ("00:80:77", "Brother Industries, LTD."),
        ("00:1B:A9", "Brother Industries, LTD."),
        ("2C:F0:5D", "Seiko Epson Corporation"),
        ("64:EB:8C", "Canon Inc."),
        ("7C:ED:8D", "Microsoft Corporation"),
        ("00:D9:D1", "Sony Interactive Entertainment Inc."),
        ("98:B6:E9", "Sony Interactive Entertainment Inc."),
        ("7C:BB:8A", "Nintendo Co.,Ltd"),
        ("B4:FB:E4", "Ubiquiti Inc"),
        ("78:8A:20", "Ubiquiti Inc"),
        ("14:CC:20", "TP-Link Technologies Co.,Ltd."),
        ("AC:84:C6", "TP-Link Technologies Co.,Ltd."),
        ("20:A6:CD", "NETGEAR"),
        ("C4:04:15", "NETGEAR"),
    ]

    conn.executemany(
        "INSERT OR IGNORE INTO oui (prefix, vendor) VALUES (?, ?)",
        seed_ouis
    )

    conn.commit()
    count = conn.execute("SELECT COUNT(*) FROM oui").fetchone()[0]
    conn.close()
    print(f"  oui.db: {count} seed OUI entries (full IEEE list loaded at first run)")


def create_os_sigs_db(db_path: str) -> None:
    """Create passive OS fingerprint signature database.

    p0f-style: TCP SYN parameters -> OS identification.
    """
    conn = sqlite3.connect(db_path)
    conn.execute("PRAGMA journal_mode=WAL")
    conn.executescript("""
        CREATE TABLE IF NOT EXISTS signatures (
            id      INTEGER PRIMARY KEY AUTOINCREMENT,
            ttl     INTEGER NOT NULL,
            window  INTEGER NOT NULL,
            df      INTEGER NOT NULL DEFAULT 1,
            mss     INTEGER DEFAULT 0,
            os      TEXT NOT NULL,
            version TEXT DEFAULT ''
        );

        CREATE INDEX IF NOT EXISTS idx_sigs_ttl_window ON signatures(ttl, window);
    """)

    # Comprehensive OS fingerprints (TTL, window, DF, MSS, OS, version)
    # Based on p0f v3 signature database and real-world observations
    sigs = [
        # ── Linux ────────────────────────────────────────────────────
        (64, 29200, 1, 1460, "Linux", "3.11-5.x (default)"),
        (64, 65535, 1, 1460, "Linux", "2.6.x"),
        (64, 5840, 1, 1460, "Linux", "2.6.x (older)"),
        (64, 14600, 1, 1460, "Linux", "3.x"),
        (64, 26883, 1, 1460, "Linux", "Android 10+"),
        (64, 14480, 1, 1460, "Linux", "Android 8-9"),
        (64, 28960, 1, 1460, "Linux", "5.x-6.x (newer)"),
        (64, 32120, 1, 1460, "Linux", "6.x (Ubuntu 24.04)"),
        (64, 29200, 1, 1380, "Linux", "3.x-5.x (VPN/tunnel)"),
        (64, 65535, 1, 1400, "Linux", "2.6.x (PPPoE)"),
        (64, 5720, 1, 1460, "Linux", "2.4.x"),
        (64, 16384, 1, 1460, "Linux", "2.2.x"),
        (64, 32767, 1, 1460, "Linux", "2.0.x"),
        (64, 26883, 1, 1400, "Linux", "Android (WiFi)"),
        (64, 64240, 1, 1460, "Linux", "5.x (RHEL 8+)"),
        (64, 14480, 1, 1460, "Linux", "Chrome OS"),
        (64, 65535, 1, 1360, "Linux", "WireGuard tunnel"),
        (64, 10240, 1, 1460, "Linux", "Alpine/musl"),
        (64, 43690, 1, 1460, "Linux", "3.x (SYN cookie)"),
        (64, 22880, 1, 1460, "Linux", "4.x-5.x (containers)"),
        (64, 62580, 1, 1460, "Linux", "6.x (Fedora 39+)"),

        # ── Windows ──────────────────────────────────────────────────
        (128, 65535, 1, 1460, "Windows", "10/11/Server 2016+"),
        (128, 8192, 1, 1460, "Windows", "7/Server 2008 R2"),
        (128, 16384, 1, 1460, "Windows", "Vista/Server 2008"),
        (128, 64240, 1, 1460, "Windows", "10 (build 1703+)"),
        (128, 65535, 1, 1400, "Windows", "10/11 (PPPoE/VPN)"),
        (128, 65535, 1, 1380, "Windows", "10/11 (tunnel)"),
        (128, 65535, 0, 1460, "Windows", "XP SP3"),
        (128, 64512, 0, 1460, "Windows", "XP SP1-SP2"),
        (128, 16384, 0, 1460, "Windows", "2000"),
        (128, 65535, 1, 1360, "Windows", "10/11 (WireGuard)"),
        (128, 64240, 1, 1400, "Windows", "10 (PPPoE)"),
        (128, 8192, 1, 1380, "Windows", "7 (VPN)"),
        (128, 65535, 1, 1440, "Windows", "Server 2019/2022"),
        (128, 65535, 1, 1460, "Windows", "Server 2022"),
        (128, 32768, 1, 1460, "Windows", "Embedded Compact"),

        # ── macOS ────────────────────────────────────────────────────
        (64, 65535, 1, 1460, "macOS", "10.x-14.x (default)"),
        (64, 65535, 1, 1400, "macOS", "10.x-14.x (PPPoE)"),
        (64, 65535, 1, 1380, "macOS", "10.x-14.x (tunnel)"),
        (64, 65535, 1, 1360, "macOS", "Sonoma (WireGuard)"),
        (64, 65535, 1, 1220, "macOS", "10.x (6in4 tunnel)"),
        (64, 32768, 1, 1460, "macOS", "10.4-10.5 (Tiger/Leopard)"),
        (64, 33304, 1, 1460, "macOS", "10.6 (Snow Leopard)"),

        # ── iOS / iPadOS / tvOS / watchOS ────────────────────────────
        (64, 65535, 1, 1460, "iOS", "15.x-17.x"),
        (64, 65535, 1, 1400, "iOS", "15.x-17.x (cellular)"),
        (64, 65535, 1, 1380, "iOS", "VPN"),
        (64, 65535, 1, 1460, "iPadOS", "16.x-17.x"),
        (64, 65535, 1, 1460, "tvOS", "16.x-17.x"),
        (64, 65535, 1, 1460, "watchOS", "9.x-10.x"),

        # ── FreeBSD / OpenBSD / NetBSD ──────────────────────────────
        (64, 65535, 1, 1460, "FreeBSD", "12.x-14.x"),
        (64, 65535, 1, 1460, "FreeBSD", "PlayStation (Orbis)"),
        (64, 32768, 1, 1460, "FreeBSD", "10.x-11.x"),
        (64, 16384, 1, 1460, "OpenBSD", "6.x-7.x"),
        (64, 16384, 1, 1460, "NetBSD", "9.x-10.x"),
        (64, 57344, 1, 1460, "DragonFly BSD", "6.x"),

        # ── Solaris / illumos ────────────────────────────────────────
        (64, 49232, 1, 1460, "Solaris", "10"),
        (64, 32806, 1, 1460, "Solaris", "11.x"),
        (255, 49640, 1, 1460, "Solaris", "8"),

        # ── Network devices ──────────────────────────────────────────
        (255, 4128, 1, 536, "Cisco IOS", "12.x-15.x"),
        (255, 16384, 1, 1460, "Cisco IOS", "17.x (IOS-XE)"),
        (255, 8192, 1, 1460, "Cisco NX-OS", ""),
        (64, 16384, 1, 1460, "Juniper JunOS", ""),
        (64, 14600, 1, 1460, "Juniper JunOS", "21.x+"),
        (64, 65535, 1, 1460, "MikroTik RouterOS", "6.x-7.x"),
        (64, 32120, 1, 1460, "Ubiquiti EdgeOS", ""),
        (64, 29200, 1, 1460, "Ubiquiti UniFi OS", ""),
        (255, 4128, 1, 536, "HP ProCurve", ""),
        (128, 8192, 1, 1460, "Arista EOS", ""),
        (64, 28960, 1, 1460, "pfSense", "2.x"),
        (64, 65535, 1, 1460, "OPNsense", "23.x+"),
        (255, 4096, 1, 536, "Fortinet FortiOS", ""),
        (255, 65535, 1, 1460, "Palo Alto PAN-OS", ""),
        (64, 65535, 1, 1460, "Aruba AOS", ""),
        (128, 65535, 1, 1460, "F5 BIG-IP", "TMOS"),

        # ── Printers ────────────────────────────────────────────────
        (128, 8192, 1, 1460, "HP JetDirect", ""),
        (128, 8192, 1, 1460, "Brother", ""),
        (128, 16384, 1, 1460, "Epson", ""),
        (128, 8192, 1, 1460, "Canon", ""),
        (128, 8192, 1, 1460, "Xerox", ""),
        (128, 8192, 1, 1460, "Ricoh", ""),
        (128, 4096, 1, 1460, "Kyocera", ""),
        (128, 8192, 1, 1460, "Lexmark", ""),
        (64, 8192, 1, 1460, "Zebra", "label printer"),

        # ── Embedded / IoT ──────────────────────────────────────────
        (64, 5840, 1, 1460, "lwIP", "embedded stack"),
        (64, 2048, 1, 1460, "uIP", "microcontroller"),
        (64, 65535, 1, 1460, "VxWorks", ""),
        (64, 4096, 1, 536, "RTOS", "generic embedded"),
        (64, 16384, 1, 1460, "QNX", ""),
        (128, 65535, 1, 1460, "Windows IoT Core", ""),
        (64, 14600, 1, 1460, "Zephyr RTOS", ""),
        (64, 5840, 1, 1460, "ESP-IDF", "ESP32"),
        (64, 1024, 1, 536, "Contiki-NG", ""),
        (64, 2144, 1, 1460, "FreeRTOS+TCP", ""),

        # ── Gaming consoles ──────────────────────────────────────────
        (64, 65535, 1, 1460, "FreeBSD", "PlayStation 4"),
        (64, 65535, 1, 1460, "FreeBSD", "PlayStation 5"),
        (128, 65535, 1, 1460, "Windows", "Xbox Series X/S"),
        (64, 65535, 1, 1460, "Nintendo", "Switch"),

        # ── Virtualization ──────────────────────────────────────────
        (64, 29200, 1, 1460, "Linux", "Docker container"),
        (64, 29200, 1, 1460, "Linux", "Kubernetes pod"),
        (64, 26883, 1, 1460, "Linux", "WSL2"),
        (128, 64240, 1, 1460, "Windows", "Hyper-V guest"),
        (64, 65535, 1, 1460, "FreeBSD", "bhyve guest"),
    ]

    conn.executemany("""
        INSERT OR IGNORE INTO signatures (ttl, window, df, mss, os, version)
        VALUES (?, ?, ?, ?, ?, ?)
    """, sigs)

    conn.commit()
    count = conn.execute("SELECT COUNT(*) FROM signatures").fetchone()[0]
    conn.close()
    print(f"  os_sigs.db: {count} OS fingerprint signatures")


def create_dhcp_fingerprints_db(db_path: str) -> None:
    """Create DHCP option 55 fingerprint database.

    Maps DHCP parameter request lists to device/OS identification.
    Fingerbank-style: the ordered list of requested DHCP options is a
    surprisingly reliable device identifier.
    """
    conn = sqlite3.connect(db_path)
    conn.execute("PRAGMA journal_mode=WAL")
    conn.executescript("""
        CREATE TABLE IF NOT EXISTS fingerprints (
            fingerprint TEXT PRIMARY KEY,
            device      TEXT NOT NULL,
            os          TEXT DEFAULT ''
        );

        CREATE INDEX IF NOT EXISTS idx_fp_device ON fingerprints(device);
    """)

    # Common DHCP fingerprints (option 55 parameter request lists)
    fps = [
        ("1,3,6,15,26,28,51,58,59", "Windows", "Windows 10/11"),
        ("1,3,6,15,26,28,51,58,59,43", "Windows", "Windows 10 (domain)"),
        ("1,15,3,6,44,46,47,31,33,121,249,43", "Windows", "Windows 7"),
        ("1,3,6,15,119,252", "macOS", "macOS 10.x-14.x"),
        ("1,121,3,6,15,119,252", "macOS", "macOS 12+"),
        ("1,3,6,15,119,252,95,44,46", "iOS", "iOS 15+"),
        ("1,3,6,28,51,58,59", "Android", "Android 10+"),
        ("1,3,6,15,26,28", "Linux", "Linux (generic)"),
        ("1,28,2,3,15,6,12", "Linux", "Linux (systemd-networkd)"),
        ("1,3,6,12,15,26,28,42", "Roku", "Roku OS"),
        ("1,3,6,12,15,28,42,125", "Amazon", "Fire TV / Echo"),
        ("1,3,6,15,28,33", "Chromecast", "Google Cast"),
        ("1,3,6,12,15,28,42", "Apple TV", "tvOS"),
        ("1,3,6,15,44,46,47", "Sonos", "Sonos"),
        ("1,3,6,12,15,28,42,120,119", "Samsung TV", "Tizen"),
        ("1,3,6,12,15,17,28,40,41,42", "HP Printer", "JetDirect"),
        ("1,3,6,12,15,28,44", "Brother Printer", "Brother"),
        ("1,3,6,12,15", "Philips Hue", "Hue Bridge"),
        ("1,3,6,15,28", "IoT Generic", "Embedded Linux"),
    ]

    conn.executemany(
        "INSERT OR IGNORE INTO fingerprints (fingerprint, device, os) VALUES (?, ?, ?)",
        fps
    )

    conn.commit()
    count = conn.execute("SELECT COUNT(*) FROM fingerprints").fetchone()[0]
    conn.close()
    print(f"  dhcp_fingerprints.db: {count} DHCP fingerprints")


def create_ja3_fingerprints_db(db_path: str) -> None:
    """Create and seed JA3 TLS client fingerprint database with 500+ profiles.

    Uses seed_ja3.py to generate comprehensive profiles across browsers,
    TLS libraries, tools, mobile clients, and IoT devices.
    """
    from seed_ja3 import seed_ja3_db
    count = seed_ja3_db(db_path)
    print(f"  ja3_fingerprints.db: {count} JA3 profiles")


def main():
    parser = argparse.ArgumentParser(description="Build SystemMonitor data databases")
    parser.add_argument(
        "--output-dir", "-o",
        default=os.path.join(os.path.dirname(os.path.dirname(__file__)), "data"),
        help="Output directory for database files"
    )
    parser.add_argument(
        "--force", "-f",
        action="store_true",
        help="Overwrite existing databases"
    )
    args = parser.parse_args()

    output_dir = Path(args.output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    print(f"Building data databases in {output_dir}/")

    databases = [
        ("innocuous_macs.db", create_innocuous_macs_db),
        ("oui.db", create_oui_db),
        ("os_sigs.db", create_os_sigs_db),
        ("dhcp_fingerprints.db", create_dhcp_fingerprints_db),
        ("ja3_fingerprints.db", create_ja3_fingerprints_db),
    ]

    for db_name, create_func in databases:
        db_path = str(output_dir / db_name)
        if os.path.exists(db_path) and not args.force:
            print(f"  {db_name}: already exists (use --force to rebuild)")
            continue
        if os.path.exists(db_path):
            os.remove(db_path)
        create_func(db_path)

    print("Done.")


if __name__ == "__main__":
    main()
