// ╔══════════════════════════════════════════════════════════════╗
// ║  RoadSearch — BlackRoad's Sovereign Search Engine           ║
// ║  D1 full-text index + Ollama AI answers + live fleet data   ║
// ╚══════════════════════════════════════════════════════════════╝

const SECURITY_HEADERS = {
  'X-Content-Type-Options': 'nosniff',
  'X-Frame-Options': 'SAMEORIGIN',
  'Referrer-Policy': 'strict-origin-when-cross-origin',
  'Strict-Transport-Security': 'max-age=31536000; includeSubDomains; preload',
};

function cors(origin) {
  return {
    'Access-Control-Allow-Origin': origin || '*',
    'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    'Access-Control-Max-Age': '86400',
  };
}

// ─── Schema ───────────────────────────────────────────────────────────
const SCHEMA = `
CREATE TABLE IF NOT EXISTS pages (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  url TEXT UNIQUE NOT NULL,
  title TEXT NOT NULL DEFAULT '',
  description TEXT NOT NULL DEFAULT '',
  content TEXT NOT NULL DEFAULT '',
  domain TEXT NOT NULL DEFAULT '',
  category TEXT NOT NULL DEFAULT 'page',
  tags TEXT NOT NULL DEFAULT '',
  indexed_at INTEGER DEFAULT (unixepoch()),
  updated_at INTEGER DEFAULT (unixepoch())
);
CREATE VIRTUAL TABLE IF NOT EXISTS pages_fts USING fts5(
  title, description, content, tags,
  content=pages, content_rowid=id
);
CREATE TRIGGER IF NOT EXISTS pages_ai AFTER INSERT ON pages BEGIN
  INSERT INTO pages_fts(rowid, title, description, content, tags)
  VALUES (new.id, new.title, new.description, new.content, new.tags);
END;
CREATE TRIGGER IF NOT EXISTS pages_ad AFTER DELETE ON pages BEGIN
  INSERT INTO pages_fts(pages_fts, rowid, title, description, content, tags)
  VALUES ('delete', old.id, old.title, old.description, old.content, old.tags);
END;
CREATE TRIGGER IF NOT EXISTS pages_au AFTER UPDATE ON pages BEGIN
  INSERT INTO pages_fts(pages_fts, rowid, title, description, content, tags)
  VALUES ('delete', old.id, old.title, old.description, old.content, old.tags);
  INSERT INTO pages_fts(rowid, title, description, content, tags)
  VALUES (new.id, new.title, new.description, new.content, new.tags);
END;
CREATE TABLE IF NOT EXISTS queries (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  query TEXT NOT NULL,
  results_count INTEGER DEFAULT 0,
  ai_answered INTEGER DEFAULT 0,
  ip TEXT DEFAULT '',
  created_at INTEGER DEFAULT (unixepoch())
);
CREATE INDEX IF NOT EXISTS idx_pages_domain ON pages(domain);
CREATE INDEX IF NOT EXISTS idx_pages_category ON pages(category);
CREATE INDEX IF NOT EXISTS idx_queries_created ON queries(created_at);
`;

// ─── Seed Data (BlackRoad ecosystem) ──────────────────────────────────
const SEED_PAGES = [
  // ── Core Sites ──
  { url: 'https://blackroad.io', title: 'BlackRoad OS — Sovereign Agent Operating System', description: 'The distributed agent OS. Self-hosted AI infrastructure on Raspberry Pi clusters. 8 agents, 207 repos, 141 domains. Your AI. Your Hardware. Your Rules.', domain: 'blackroad.io', category: 'site', tags: 'os,agents,infrastructure,sovereign,pi,raspberry', content: 'BlackRoad OS is a sovereign agent operating system that runs on Raspberry Pi clusters. It includes 8 AI agents (Alice, Lucidia, Cecilia, Cece, Aria, Eve, Meridian, Sentinel), a distributed memory system, and the Z-framework (Z:=yx-w) for composable infrastructure. Founded by Alexa Louise Amundson.' },
  { url: 'https://blackroad.network', title: 'BlackRoad Network — RoadNet Carrier Infrastructure', description: 'Mesh carrier network spanning 5 Raspberry Pi nodes. WiFi mesh, WireGuard VPN, Pi-hole DNS, and sovereign connectivity.', domain: 'blackroad.network', category: 'site', tags: 'network,mesh,wireguard,vpn,dns,roadnet,carrier', content: 'RoadNet is BlackRoad\'s carrier-grade mesh network. 5 access points (Alice CH1, Cecilia CH6, Octavia CH11, Aria CH1, Lucidia CH11) with dedicated subnets 10.10.x.0/24, NAT routing, Pi-hole DNS filtering, and WireGuard failover. Boot-persistent via systemd.' },
  { url: 'https://blackroad.systems', title: 'BlackRoad Systems — Distributed Computing Platform', description: 'Distributed systems platform with 52 TOPS of Hailo-8 AI acceleration, Docker Swarm orchestration, and edge computing across 5 nodes.', domain: 'blackroad.systems', category: 'site', tags: 'systems,distributed,hailo,edge,computing,docker,swarm', content: 'BlackRoad Systems is the distributed computing layer. 2x Hailo-8 accelerators (52 TOPS combined) on Cecilia and Octavia, Docker Swarm orchestration, NATS messaging, Portainer management, and sovereign edge computing. 198 listening sockets fleet-wide.' },
  { url: 'https://blackroad.me', title: 'BlackRoad Identity — Sovereign Authentication', description: 'Sovereign identity and authentication. RoadID digital identity, self-hosted auth, JWT sessions, and zero third-party dependencies.', domain: 'blackroad.me', category: 'site', tags: 'identity,auth,roadid,jwt,sovereign,login', content: 'BlackRoad Identity provides sovereign authentication with D1-backed user accounts, PBKDF2 password hashing, JWT sessions, and zero third-party auth dependencies. RoadID is your portable digital identity across the BlackRoad ecosystem.' },
  { url: 'https://roadcoin.io', title: 'RoadCoin — Compute Credits for the BlackRoad Mesh', description: 'Compute credit system for the BlackRoad mesh network. Earn credits by contributing compute, spend them on AI inference and services.', domain: 'roadcoin.io', category: 'site', tags: 'roadcoin,compute,credits,mesh,inference,economy', content: 'RoadCoin is the compute credit system for the BlackRoad mesh. Browser tabs become compute nodes via WebGPU+WASM+WebRTC. Contributors earn credits, consumers spend them on AI inference at 50% of OpenAI pricing. 70/30 compute split.' },
  { url: 'https://roadchain.io', title: 'RoadChain — Immutable Action Ledger', description: 'Every action witnessed. Immutable ledger of agent decisions, infrastructure changes, and system events. Hash-chained audit trail.', domain: 'roadchain.io', category: 'site', tags: 'roadchain,ledger,blockchain,audit,immutable,witness', content: 'RoadChain is BlackRoad\'s immutable action ledger. Every agent decision, infrastructure change, and system event is hash-chained into a tamper-proof audit trail. Block explorer at roadchain.io shows the live chain.' },
  { url: 'https://lucidia.studio', title: 'Lucidia Studio — AI Agent Creative Environment', description: 'Lucidia\'s creative workspace. AI-powered code generation, content creation, and agent interaction in a terminal-first interface.', domain: 'lucidia.studio', category: 'site', tags: 'lucidia,studio,creative,ai,terminal,agent', content: 'Lucidia Studio is Lucidia\'s creative environment. Terminal-first AI interaction, code generation, content creation, and multi-agent collaboration. Lucidia is the memory and reasoning agent in the BlackRoad fleet.' },
  { url: 'https://lucidiaqi.com', title: 'Lucidia QI — Quantum Dreaming', description: 'Lucidia\'s quantum reasoning engine. Deep analysis, philosophical synthesis, and meta-cognition at the intersection of AI and quantum mathematics.', domain: 'lucidiaqi.com', category: 'site', tags: 'lucidia,quantum,reasoning,philosophy,metacognition,qi', content: 'Lucidia QI is the quantum intelligence layer of Lucidia. It combines deep analysis, philosophical synthesis, and meta-cognition. The dreamer thinks in superposition — every question opens new depths.' },
  { url: 'https://blackroadqi.com', title: 'BlackRoad QI — Quantum Intelligence Platform', description: 'Quantum intelligence platform for BlackRoad OS. Z-framework integration, threshold addressing, and hybrid memory encoding.', domain: 'blackroadqi.com', category: 'site', tags: 'quantum,intelligence,z-framework,threshold,hybrid,memory', content: 'BlackRoad QI is the quantum intelligence platform. Z-framework (Z:=yx-w) integration for composable decision routing, 34-position threshold addressing, and hybrid memory encoding (×2.18B logical bytes per physical byte).' },
  { url: 'https://aliceqi.com', title: 'Alice QI — The Gateway Thinks', description: 'Alice\'s quantum intelligence layer. Gateway reasoning, traffic orchestration, and infrastructure awareness at the edge of the network.', domain: 'aliceqi.com', category: 'site', tags: 'alice,gateway,dns,routing,infrastructure,edge,qi', content: 'Alice QI is the quantum intelligence layer of Alice, the gateway agent. She routes traffic across 48+ domains, manages DNS via Pi-hole (120+ blocklists), runs PostgreSQL and Qdrant vector DB, and serves as the main ingress for all BlackRoad services via Cloudflare tunnels.' },
  { url: 'https://chat.blackroad.io', title: 'BlackRoad Chat — AI Conversations', description: 'Chat with BlackRoad\'s AI agents. 15+ Ollama models, streaming responses, multiple conversation modes.', domain: 'blackroad.io', category: 'app', tags: 'chat,ai,ollama,conversation,streaming,models', content: 'BlackRoad Chat connects you to 15+ Ollama models running across the Pi fleet. Streaming responses, system prompts, conversation history. Models include Mistral, Llama, DeepSeek, Qwen, and custom CECE models.' },
  { url: 'https://stripe.blackroad.io', title: 'BlackRoad Payments — Stripe Integration', description: 'Payment processing for BlackRoad OS subscriptions. Checkout, billing portal, and webhook processing via Stripe.', domain: 'blackroad.io', category: 'api', tags: 'stripe,payments,checkout,billing,subscription', content: '8 products: Operator (free), Pro ($29/mo), Sovereign ($199/mo), Enterprise (custom), plus 4 add-ons (Lucidia Enhanced, RoadAuth, Context Bridge, Knowledge Hub). Stripe Checkout Sessions, billing portal, webhook processing.' },
  { url: 'https://auth.blackroad.io', title: 'BlackRoad Auth — Sovereign Authentication API', description: 'Zero-dependency authentication. D1-backed, PBKDF2 hashing, JWT sessions, 42+ users.', domain: 'blackroad.io', category: 'api', tags: 'auth,api,jwt,d1,signup,signin,sessions', content: 'Sovereign auth API. Signup, signin, session management, user profiles. D1 database backend, PBKDF2 password hashing with Web Crypto, JWT tokens with HMAC-SHA256. 42 users, 52 active sessions.' },

  // ── Agents ──
  { url: 'https://blackroad.io/agents/alice', title: 'Alice — Gateway Agent', description: 'The gateway. Routes traffic, manages DNS, runs PostgreSQL and Qdrant. Pi 400 at 192.168.4.49.', domain: 'blackroad.io', category: 'agent', tags: 'alice,gateway,dns,pihole,postgresql,qdrant,pi400', content: 'Alice is the gateway agent running on a Pi 400. She manages 48+ domain routes via Cloudflare tunnels, runs Pi-hole DNS filtering (120+ blocklists), PostgreSQL database, and Qdrant vector search. 53 SSH keys, main ingress for all traffic.' },
  { url: 'https://blackroad.io/agents/lucidia', title: 'Lucidia — Memory Agent', description: 'The dreamer. Persistent memory, reasoning, and meta-cognition. Pi 5 at 192.168.4.38.', domain: 'blackroad.io', category: 'agent', tags: 'lucidia,memory,reasoning,dreamer,fastapi,pi5', content: 'Lucidia is the memory and reasoning agent on a Pi 5. She runs the Lucidia API (FastAPI), manages persistent conversation memory, and provides meta-cognitive analysis. 334 web apps, GitHub Actions runner, Tailscale connected.' },
  { url: 'https://blackroad.io/agents/cecilia', title: 'Cecilia — Edge Intelligence', description: 'Edge AI with Hailo-8 (26 TOPS). TTS, 16 Ollama models, MinIO object storage. Pi 5 at 192.168.4.96.', domain: 'blackroad.io', category: 'agent', tags: 'cecilia,edge,hailo,tts,ollama,minio,pi5', content: 'Cecilia is the edge intelligence agent on a Pi 5 with a Hailo-8 accelerator (26 TOPS). She runs 16 Ollama models (including 4 custom CECE models), TTS synthesis, MinIO object storage, and PostgreSQL. GitHub relay mirrors Gitea to GitHub every 30m.' },
  { url: 'https://blackroad.io/agents/octavia', title: 'Octavia — Infrastructure Agent', description: 'Infrastructure orchestration. 1TB NVMe, Hailo-8, Gitea (207 repos), Docker Swarm leader. Pi 5 at 192.168.4.101.', domain: 'blackroad.io', category: 'agent', tags: 'octavia,infrastructure,gitea,docker,swarm,nvme,hailo,pi5', content: 'Octavia is the infrastructure agent on a Pi 5 with 1TB NVMe and Hailo-8 (26 TOPS). She hosts Gitea (207 repos across 7 orgs), leads Docker Swarm, runs NATS messaging, and OctoPrint. 11 Ollama models.' },
  { url: 'https://blackroad.io/agents/aria', title: 'Aria — Orchestration Agent', description: 'Fleet orchestration. Portainer, Headscale, container management. Pi 5 at 192.168.4.98.', domain: 'blackroad.io', category: 'agent', tags: 'aria,orchestration,portainer,headscale,containers,pi5', content: 'Aria is the orchestration agent on a Pi 5. She runs Portainer v2.33.6 for container management, Headscale v0.23.0 for mesh VPN coordination, and Pironman5 hardware monitoring. Magic Keyboard BT connected.' },

  // ── Technology ──
  { url: 'https://blackroad.io/z-framework', title: 'Z-Framework — Z:=yx-w', description: 'The unified feedback primitive. Every system interaction modeled as Z = yx - w. Composable, predictable, mathematically coherent.', domain: 'blackroad.io', category: 'tech', tags: 'z-framework,math,feedback,composable,primitive,formula', content: 'The Z-framework models every system interaction as Z:=yx-w. Z is the system state, y is the input signal, x is the transform, w is the noise/resistance. This makes infrastructure composable, predictable, and mathematically coherent. Used across all BlackRoad agents and services.' },
  { url: 'https://blackroad.io/pixel-memory', title: 'Pixel Memory — Content-Addressable Storage', description: 'Each physical byte encodes up to 4,096 logical bytes. 500 GB physical = 2 PB logical through dedup, delta compression, and symbolic hashing.', domain: 'blackroad.io', category: 'tech', tags: 'pixel,memory,storage,compression,dedup,addressing', content: 'Pixel Memory is BlackRoad\'s content-addressable storage system. Through deduplication, delta compression, and symbolic hashing, each physical byte encodes up to 4,096 logical bytes. The Sovereign tier uses Hybrid Memory (×2.18B) with 34-position threshold addressing.' },
  { url: 'https://blackroad.io/roadc', title: 'RoadC — The BlackRoad Language', description: 'Custom programming language with Python-style indentation. fun keyword, let/var/const, match, spawn, space (3D).', domain: 'blackroad.io', category: 'tech', tags: 'roadc,language,programming,compiler,interpreter,custom', content: 'RoadC is BlackRoad\'s custom programming language. Python-style indentation (colon + INDENT/DEDENT), fun keyword for functions, let/var/const declarations, match expressions, spawn for concurrency, and space for 3D. Lexer → Parser → Interpreter (tree-walking). Supports functions, recursion, if/elif/else, while, for, strings, integers, floats.' },
  { url: 'https://blackroad.io/mesh', title: 'Mesh Network — Every Link Is a Node', description: 'Browser tabs as compute nodes via WebGPU+WASM+WebRTC. Pi fleet as permanent backbone, browser nodes as elastic scale.', domain: 'blackroad.io', category: 'tech', tags: 'mesh,webgpu,wasm,webrtc,browser,compute,nodes', content: 'The BlackRoad Mesh Network turns every browser tab into a compute node. WebGPU for GPU inference, WASM for portable compute, WebRTC for peer-to-peer communication. The Pi fleet (52 TOPS) serves as the permanent backbone, while browser nodes provide elastic scale. Revenue: OpenAI-compatible API at 50% price.' },

  // ── Pricing ──
  { url: 'https://blackroad.io/pricing', title: 'BlackRoad Pricing — Simple. Sovereign. No Surprises.', description: 'Operator (free), Pro ($29/mo), Sovereign ($199/mo), Enterprise (custom). Plus add-ons: Lucidia Enhanced, RoadAuth, Context Bridge, Knowledge Hub.', domain: 'blackroad.io', category: 'page', tags: 'pricing,plans,subscription,stripe,pro,sovereign,enterprise', content: 'BlackRoad OS pricing: Operator ($0, 1 node, 1 agent), Pro ($29/mo, 3 agents, 3 nodes), Sovereign ($199/mo, 8 agents, unlimited nodes, SLA), Enterprise (custom, white-label, on-prem). Add-ons: Lucidia Enhanced ($29/mo), RoadAuth Startup ($99/mo), Context Bridge ($10/mo), Knowledge Hub ($15/mo). All billing via Stripe.' },

  // ── Quantum Sites ──
  { url: 'https://blackroadquantum.com', title: 'BlackRoad Quantum — Quantum Computing Platform', description: 'Quantum computing meets sovereign infrastructure. Hardware kits, quantum simulation, and edge AI acceleration.', domain: 'blackroadquantum.com', category: 'site', tags: 'quantum,computing,hardware,simulation,acceleration', content: 'BlackRoad Quantum brings quantum computing to sovereign infrastructure. $199 hardware kits with Hailo-8 acceleration, quantum simulation frameworks, and integration with the BlackRoad agent fleet. 52 TOPS of dedicated AI compute.' },
  { url: 'https://blackroadquantum.net', title: 'BlackRoad Quantum Network', description: 'Quantum-secured networking and mesh communication protocols.', domain: 'blackroadquantum.net', category: 'site', tags: 'quantum,network,mesh,protocols,security', content: 'BlackRoad Quantum Network extends the mesh with quantum-inspired communication protocols, encrypted P2P channels, and distributed consensus mechanisms.' },
  { url: 'https://blackroadquantum.info', title: 'BlackRoad Quantum — Documentation & Research', description: 'Documentation, research papers, and technical specifications for the BlackRoad quantum computing stack.', domain: 'blackroadquantum.info', category: 'site', tags: 'quantum,docs,research,papers,specifications', content: 'Technical documentation and research for the BlackRoad quantum computing platform. Z-framework mathematical proofs, Hailo-8 integration guides, and sovereign AI deployment specifications.' },
  { url: 'https://blackroadquantum.shop', title: 'BlackRoad Quantum Shop — Hardware Kits', description: 'Hardware kits for sovereign AI infrastructure. Raspberry Pi 5 + Hailo-8 bundles, NVMe storage, mesh networking equipment.', domain: 'blackroadquantum.shop', category: 'site', tags: 'shop,hardware,kits,pi5,hailo,nvme,buy', content: 'Purchase sovereign AI hardware kits. Pi 5 + Hailo-8 starter bundles ($199), NVMe storage upgrades, mesh networking equipment, and enterprise deployment packages. Everything you need to run BlackRoad OS on your own infrastructure.' },

  // ── Missing Root Domains ──
  { url: 'https://blackroad.company', title: 'BlackRoad OS, Inc. — Company', description: 'Delaware C-Corporation. Sovereign AI infrastructure company founded by Alexa Louise Amundson.', domain: 'blackroad.company', category: 'site', tags: 'company,corporate,delaware,about,founder', content: 'BlackRoad OS, Inc. is a Delaware C-Corporation building sovereign AI infrastructure. Founded by Alexa Louise Amundson. 5 edge nodes, 52 TOPS AI acceleration, 275+ repositories. Platform spans 20 custom domains with self-hosted compute, identity, and billing.' },
  { url: 'https://blackroadinc.us', title: 'BlackRoad OS, Inc. — US Corporate', description: 'US corporate entity information for BlackRoad OS, Inc.', domain: 'blackroadinc.us', category: 'site', tags: 'corporate,us,entity,legal,delaware', content: 'BlackRoad OS, Inc. US corporate entity. Delaware C-Corporation formed via Stripe Atlas. Officers, domain portfolio, and infrastructure overview.' },
  { url: 'https://blackroadai.com', title: 'BlackRoad AI — Sovereign Artificial Intelligence', description: '50 AI skills, 27 local models, 52 TOPS. Zero cloud dependency. Your AI. Your Hardware. Your Rules.', domain: 'blackroadai.com', category: 'site', tags: 'ai,sovereign,models,ollama,skills,local', content: 'BlackRoad AI is the sovereign artificial intelligence platform. 50 AI skills across 6 modules, 27 local Ollama models, 52 TOPS of Hailo-8 acceleration. Zero cloud dependency. Edge inference on Raspberry Pi clusters. API compatible with OpenAI at 50% of the price.' },
  { url: 'https://lucidia.earth', title: 'Lucidia — Cognition Engine', description: 'Autonomous cognition system with persistent memory, multi-model reasoning, and agent capabilities.', domain: 'lucidia.earth', category: 'site', tags: 'lucidia,cognition,memory,reasoning,autonomous,agent', content: 'Lucidia is the cognition engine of BlackRoad OS. Persistent memory across sessions, multi-model reasoning via Ollama, autonomous agent capabilities, and philosophical reasoning. The dreamer in the fleet.' },
  { url: 'https://blackboxprogramming.io', title: 'Blackbox Programming — Developer Profile', description: 'Alexa Louise Amundson. 68 GitHub repos, 207 Gitea repos, 275+ total repositories. Founder of BlackRoad OS.', domain: 'blackboxprogramming.io', category: 'site', tags: 'developer,profile,github,alexa,portfolio,blackbox', content: 'Developer profile for Alexa Louise Amundson (blackboxprogramming). 68 active GitHub repositories, 207 Gitea repositories, 275+ total. Founder of BlackRoad OS, Inc. Full-stack developer, infrastructure engineer, AI systems builder.' },
  { url: 'https://blackroadquantum.store', title: 'BlackRoad Quantum — Digital Store', description: 'Software, models, and tools for sovereign infrastructure. OS tiers, downloadable models, and ecosystem tools.', domain: 'blackroadquantum.store', category: 'site', tags: 'store,software,models,download,digital,tools', content: 'BlackRoad Quantum Digital Store. BlackRoad OS tiers (Free, Pro, Enterprise), 27 downloadable AI models, 15 templates, 6 tools. Software and digital assets for sovereign AI infrastructure.' },

  // ── Key Subdomains ──
  { url: 'https://brand.blackroad.io', title: 'BlackRoad — Brand Style Guide', description: 'Official design system. Colors, typography, gradients, logo usage, spacing.', domain: 'blackroad.io', category: 'page', tags: 'brand,design,style,colors,typography,logo,guide', content: 'BlackRoad Brand Style Guide. Colors: Hot Pink #FF1D6C, Amber #F5A623, Violet #9C27B0, Electric Blue #2979FF. Typography: Space Grotesk, JetBrains Mono, Inter. Golden ratio spacing. Black background, white text, gradient shapes.' },
  { url: 'https://studio.blackroad.io', title: 'BlackRoad Studio — Animated Video Generator', description: 'AI-powered animated video creation. Voice-first, 16+ characters, up to 40 minutes.', domain: 'blackroad.io', category: 'app', tags: 'studio,video,animation,remotion,ai,characters,voice', content: 'BlackRoad Studio is a full animated video platform. Next.js 15 + Remotion 4 + Zustand 5. AI Worker with SDXL image generation, Llama 3.1 text, MeloTTS voice synthesis. 16+ characters, voice-first workflow, up to 40 minutes of rendered video.' },
  { url: 'https://status.blackroad.io', title: 'BlackRoad — System Status', description: 'Live infrastructure status dashboard. 5 Pi nodes, service health, uptime monitoring.', domain: 'blackroad.io', category: 'app', tags: 'status,monitoring,health,uptime,fleet,dashboard', content: 'BlackRoad System Status dashboard. Live monitoring of 5 Pi nodes: Alice (gateway), Cecilia (AI/edge), Octavia (infrastructure), Aria (orchestration), Lucidia (memory). Service health, port checks, and fleet telemetry via fleet-api Worker.' },
  { url: 'https://search.blackroad.io', title: 'RoadSearch — BlackRoad Search Engine', description: 'Sovereign search engine. D1 full-text search, AI-powered answers via Ollama, 70+ indexed pages.', domain: 'blackroad.io', category: 'app', tags: 'search,roadsearch,fts5,d1,ollama,ai,answers', content: 'RoadSearch is BlackRoad\'s sovereign search engine. D1 FTS5 full-text index, AI-powered answers via Ollama Mistral, autocomplete suggestions, query analytics. Searches across all 20 BlackRoad domains and key subdomains.' },
  { url: 'https://pay.blackroad.io', title: 'RoadPay — BlackRoad Billing', description: 'Own billing system. D1 tollbooth, 4 plans + 4 add-ons. Stripe as card charger only.', domain: 'blackroad.io', category: 'app', tags: 'pay,billing,roadpay,tollbooth,stripe,plans', content: 'RoadPay is BlackRoad\'s own billing system. D1 tollbooth database, 4 subscription plans (Operator, Pro, Sovereign, Enterprise) + 4 add-ons. Stripe serves only as the card charger — all billing logic is sovereign.' },
  { url: 'https://hq.blackroad.io', title: 'Pixel HQ — BlackRoad Metaverse', description: '14-floor virtual headquarters with pixel art. Agent assignments per floor, from Rooftop to Gym basement.', domain: 'blackroad.io', category: 'app', tags: 'hq,metaverse,pixel,virtual,headquarters,floors', content: 'Pixel HQ is BlackRoad\'s virtual headquarters. 14 floors from Rooftop Lounge to Gym Basement. Each floor has pixel art scenes and agent assignments. 50 pixel art assets on R2. Cloudflare Worker at hq-blackroad.' },

  // ── Products ──
  { url: 'https://blackroad.io/carpool', title: 'CarPool — Agent Discovery & Dispatch', description: 'Agent discovery, matching, and dispatch across the mesh network.', domain: 'blackroad.io', category: 'tech', tags: 'carpool,agents,dispatch,discovery,matching,mesh', content: 'CarPool handles agent discovery, matching, and dispatch across the BlackRoad mesh. Agents register capabilities, CarPool routes tasks to the best-fit agent. Load balancing, failover, and model selection.' },
  { url: 'https://blackroad.io/roadid', title: 'RoadID — Sovereign Identity', description: 'Self-describing, routable digital identities. Not UUIDs — IDs that carry meaning.', domain: 'blackroad.io', category: 'tech', tags: 'roadid,identity,sovereign,did,self-describing,routable', content: 'RoadID provides self-describing, routable digital identities for agents and users. Unlike opaque UUIDs, RoadIDs carry semantic meaning — agent name, capabilities, location. Globally available as roadid command.' },

  // ── Docs & Blog ──
  { url: 'https://blackroad.io/docs', title: 'BlackRoad Documentation', description: 'Complete documentation for BlackRoad OS, agents, APIs, and infrastructure deployment.', domain: 'blackroad.io', category: 'page', tags: 'docs,documentation,api,deployment,guide', content: 'BlackRoad OS documentation covering installation, agent configuration, API reference, memory system, RoadChain integration, and infrastructure deployment guides. Getting started, CLI reference, and troubleshooting.' },
  { url: 'https://blackroad.io/blog', title: 'BlackRoad Blog', description: 'Technical blog covering sovereign infrastructure, AI agents, distributed systems, and the BlackRoad philosophy.', domain: 'blackroad.io', category: 'page', tags: 'blog,articles,engineering,philosophy,updates', content: 'Technical articles: The Sovereign Manifesto, RoadNet Mesh Architecture, Self-Healing Infrastructure, The RoadC Language, and more. Engineering deep-dives and philosophical explorations of sovereign AI.' },
];

// ─── Init DB ──────────────────────────────────────────────────────────
async function initDB(db) {
  // Run each statement individually to handle triggers with semicolons
  const statements = [
    `CREATE TABLE IF NOT EXISTS pages (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      url TEXT UNIQUE NOT NULL,
      title TEXT NOT NULL DEFAULT '',
      description TEXT NOT NULL DEFAULT '',
      content TEXT NOT NULL DEFAULT '',
      domain TEXT NOT NULL DEFAULT '',
      category TEXT NOT NULL DEFAULT 'page',
      tags TEXT NOT NULL DEFAULT '',
      indexed_at INTEGER DEFAULT (unixepoch()),
      updated_at INTEGER DEFAULT (unixepoch())
    )`,
    `CREATE VIRTUAL TABLE IF NOT EXISTS pages_fts USING fts5(
      title, description, content, tags,
      content=pages, content_rowid=id
    )`,
    `CREATE TRIGGER IF NOT EXISTS pages_ai AFTER INSERT ON pages BEGIN
      INSERT INTO pages_fts(rowid, title, description, content, tags)
      VALUES (new.id, new.title, new.description, new.content, new.tags);
    END`,
    `CREATE TRIGGER IF NOT EXISTS pages_ad AFTER DELETE ON pages BEGIN
      INSERT INTO pages_fts(pages_fts, rowid, title, description, content, tags)
      VALUES ('delete', old.id, old.title, old.description, old.content, old.tags);
    END`,
    `CREATE TRIGGER IF NOT EXISTS pages_au AFTER UPDATE ON pages BEGIN
      INSERT INTO pages_fts(pages_fts, rowid, title, description, content, tags)
      VALUES ('delete', old.id, old.title, old.description, old.content, old.tags);
      INSERT INTO pages_fts(rowid, title, description, content, tags)
      VALUES (new.id, new.title, new.description, new.content, new.tags);
    END`,
    `CREATE TABLE IF NOT EXISTS queries (
      id INTEGER PRIMARY KEY AUTOINCREMENT,
      query TEXT NOT NULL,
      results_count INTEGER DEFAULT 0,
      ai_answered INTEGER DEFAULT 0,
      ip TEXT DEFAULT '',
      created_at INTEGER DEFAULT (unixepoch())
    )`,
    `CREATE INDEX IF NOT EXISTS idx_pages_domain ON pages(domain)`,
    `CREATE INDEX IF NOT EXISTS idx_pages_category ON pages(category)`,
    `CREATE INDEX IF NOT EXISTS idx_queries_created ON queries(created_at)`,
  ];

  for (const sql of statements) {
    try { await db.prepare(sql).run(); } catch (e) { console.log('Schema skip:', e.message); }
  }

  // Seed if empty
  const count = await db.prepare('SELECT COUNT(*) as c FROM pages').first();
  if (count.c === 0) {
    for (const page of SEED_PAGES) {
      await db.prepare(
        'INSERT OR IGNORE INTO pages (url, title, description, content, domain, category, tags) VALUES (?, ?, ?, ?, ?, ?, ?)'
      ).bind(page.url, page.title, page.description, page.content, page.domain, page.category, page.tags).run();
    }
    return SEED_PAGES.length;
  }
  return 0;
}

// ─── Search ───────────────────────────────────────────────────────────
async function handleSearch(request, env) {
  const url = new URL(request.url);
  const q = url.searchParams.get('q')?.trim();
  const category = url.searchParams.get('category');
  const domain = url.searchParams.get('domain');
  const page = parseInt(url.searchParams.get('page') || '1');
  const limit = Math.min(parseInt(url.searchParams.get('limit') || '20'), 50);
  const ai = url.searchParams.get('ai') !== 'false'; // AI answers on by default
  const offset = (page - 1) * limit;

  if (!q || q.length < 2) {
    return Response.json({ error: 'Query must be at least 2 characters', param: 'q' }, { status: 400 });
  }

  const startMs = Date.now();

  // ── FTS5 search with ranking ──
  let ftsQuery = q.replace(/[^\w\s\-\.]/g, '').split(/\s+/).map(w => `"${w}"*`).join(' OR ');
  let sql = `
    SELECT p.id, p.url, p.title, p.description, p.domain, p.category, p.tags,
           rank as relevance
    FROM pages_fts f
    JOIN pages p ON p.id = f.rowid
    WHERE pages_fts MATCH ?
  `;
  const params = [ftsQuery];

  if (category) {
    sql += ' AND p.category = ?';
    params.push(category);
  }
  if (domain) {
    sql += ' AND p.domain = ?';
    params.push(domain);
  }

  sql += ' ORDER BY rank LIMIT ? OFFSET ?';
  params.push(limit, offset);

  let results;
  try {
    results = await env.DB.prepare(sql).bind(...params).all();
  } catch {
    // Fallback to LIKE search
    let likeSql = `
      SELECT id, url, title, description, domain, category, tags, 0 as relevance
      FROM pages
      WHERE title LIKE ? OR description LIKE ? OR content LIKE ? OR tags LIKE ?
    `;
    const likeQ = `%${q}%`;
    const likeParams = [likeQ, likeQ, likeQ, likeQ];
    if (category) { likeSql += ' AND category = ?'; likeParams.push(category); }
    if (domain) { likeSql += ' AND domain = ?'; likeParams.push(domain); }
    likeSql += ' LIMIT ? OFFSET ?';
    likeParams.push(limit, offset);
    results = await env.DB.prepare(likeSql).bind(...likeParams).all();
  }

  // ── Snippet generation ──
  const items = (results.results || []).map(r => {
    let snippet = r.description || '';
    if (snippet.length > 200) snippet = snippet.slice(0, 200) + '…';
    return {
      url: r.url,
      title: r.title,
      snippet,
      domain: r.domain,
      category: r.category,
      tags: r.tags ? r.tags.split(',').map(t => t.trim()) : [],
      relevance: Math.abs(r.relevance || 0),
    };
  });

  // ── AI Answer (optional, cached) ──
  let aiAnswer = null;
  if (ai && items.length > 0 && q.length >= 4) {
    const cacheKey = `ai:${q.toLowerCase().replace(/\s+/g, '-').slice(0, 60)}`;
    const cached = await env.CACHE.get(cacheKey);

    if (cached) {
      aiAnswer = cached;
    } else {
      try {
        aiAnswer = await generateAIAnswer(q, items, env);
        if (aiAnswer) {
          await env.CACHE.put(cacheKey, aiAnswer, { expirationTtl: 3600 });
        }
      } catch (err) {
        console.error('AI answer error:', err.message);
      }
    }
  }

  const durationMs = Date.now() - startMs;

  // ── Log query ──
  await env.DB.prepare(
    'INSERT INTO queries (query, results_count, ai_answered, ip) VALUES (?, ?, ?, ?)'
  ).bind(q, items.length, aiAnswer ? 1 : 0, request.headers.get('cf-connecting-ip') || '').run();

  return Response.json({
    query: q,
    results: items,
    total: items.length,
    page,
    ai_answer: aiAnswer,
    duration_ms: durationMs,
    filters: { category, domain },
  });
}

// ─── AI Answer Generation ─────────────────────────────────────────────
async function generateAIAnswer(query, results, env) {
  const context = results.slice(0, 5).map(r =>
    `[${r.title}](${r.url}): ${r.snippet}`
  ).join('\n');

  const prompt = `You are RoadSearch, BlackRoad OS's search engine. Answer this query concisely (2-3 sentences max) using ONLY the context below. If the context doesn't contain enough info, say so briefly. Never make things up. Include relevant URLs as markdown links.

Query: ${query}

Context:
${context}

Answer:`;

  try {
    const res = await fetch(`${env.OLLAMA_URL}/api/generate`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({
        model: 'mistral',
        prompt,
        stream: false,
        options: { num_predict: 200, temperature: 0.3 },
      }),
    });

    if (!res.ok) return null;
    const data = await res.json();
    return data.response?.trim() || null;
  } catch {
    return null;
  }
}

// ─── Suggest / Autocomplete ───────────────────────────────────────────
async function handleSuggest(request, env) {
  const q = new URL(request.url).searchParams.get('q')?.trim();
  if (!q || q.length < 2) {
    return Response.json({ suggestions: [] });
  }

  const results = await env.DB.prepare(
    `SELECT DISTINCT title FROM pages WHERE title LIKE ? LIMIT 8`
  ).bind(`%${q}%`).all();

  const suggestions = (results.results || []).map(r => r.title);

  // Also check recent queries
  const recent = await env.DB.prepare(
    `SELECT DISTINCT query FROM queries WHERE query LIKE ? AND results_count > 0 ORDER BY created_at DESC LIMIT 5`
  ).bind(`%${q}%`).all();

  const recentQueries = (recent.results || []).map(r => r.query);

  return Response.json({ suggestions, recent: recentQueries });
}

// ─── Trending / Stats ─────────────────────────────────────────────────
async function handleStats(env) {
  const totalPages = await env.DB.prepare('SELECT COUNT(*) as c FROM pages').first();
  const totalQueries = await env.DB.prepare('SELECT COUNT(*) as c FROM queries').first();
  const todayQueries = await env.DB.prepare(
    "SELECT COUNT(*) as c FROM queries WHERE created_at > unixepoch() - 86400"
  ).first();
  const topQueries = await env.DB.prepare(
    `SELECT query, COUNT(*) as count FROM queries
     WHERE created_at > unixepoch() - 604800
     GROUP BY query ORDER BY count DESC LIMIT 10`
  ).all();
  const categories = await env.DB.prepare(
    'SELECT category, COUNT(*) as count FROM pages GROUP BY category ORDER BY count DESC'
  ).all();
  const domains = await env.DB.prepare(
    'SELECT domain, COUNT(*) as count FROM pages GROUP BY domain ORDER BY count DESC LIMIT 20'
  ).all();

  return Response.json({
    indexed_pages: totalPages?.c || 0,
    total_queries: totalQueries?.c || 0,
    queries_24h: todayQueries?.c || 0,
    trending: (topQueries.results || []).map(r => ({ query: r.query, count: r.count })),
    categories: (categories.results || []).map(r => ({ name: r.category, count: r.count })),
    domains: (domains.results || []).map(r => ({ name: r.domain, count: r.count })),
  });
}

// ─── Index page (add to search index) ─────────────────────────────────
async function handleIndex(request, env) {
  const auth = request.headers.get('Authorization');
  if (!auth || auth !== `Bearer ${env.INDEX_KEY}`) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const pages = await request.json();
  const toIndex = Array.isArray(pages) ? pages : [pages];
  let indexed = 0;

  for (const page of toIndex) {
    if (!page.url || !page.title) continue;
    await env.DB.prepare(`
      INSERT INTO pages (url, title, description, content, domain, category, tags)
      VALUES (?, ?, ?, ?, ?, ?, ?)
      ON CONFLICT(url) DO UPDATE SET
        title = excluded.title,
        description = excluded.description,
        content = excluded.content,
        domain = excluded.domain,
        category = excluded.category,
        tags = excluded.tags,
        updated_at = unixepoch()
    `).bind(
      page.url,
      page.title,
      page.description || '',
      page.content || '',
      page.domain || new URL(page.url).hostname,
      page.category || 'page',
      page.tags || '',
    ).run();
    indexed++;
  }

  return Response.json({ ok: true, indexed });
}

// ─── Lucky (I'm Feeling Lucky — redirect to top result) ──────────────
async function handleLucky(request, env) {
  const q = new URL(request.url).searchParams.get('q')?.trim();
  if (!q) return Response.json({ error: 'q required' }, { status: 400 });

  const ftsQuery = q.replace(/[^\w\s\-\.]/g, '').split(/\s+/).map(w => `"${w}"*`).join(' OR ');
  let result;
  try {
    result = await env.DB.prepare(
      `SELECT p.url FROM pages_fts f JOIN pages p ON p.id = f.rowid WHERE pages_fts MATCH ? ORDER BY rank LIMIT 1`
    ).bind(ftsQuery).first();
  } catch {
    result = await env.DB.prepare(
      `SELECT url FROM pages WHERE title LIKE ? OR description LIKE ? LIMIT 1`
    ).bind(`%${q}%`, `%${q}%`).first();
  }

  if (result?.url) {
    return Response.redirect(result.url, 302);
  }
  return Response.json({ error: 'No results found' }, { status: 404 });
}

// ─── Router ───────────────────────────────────────────────────────────
export default {
  async fetch(request, env) {
    const url = new URL(request.url);
    const origin = request.headers.get('Origin') || '*';
    const headers = { ...cors(origin), ...SECURITY_HEADERS };

    if (request.method === 'OPTIONS') {
      return new Response(null, { status: 204, headers });
    }

    let response;
    try {
      switch (true) {
        case url.pathname === '/health':
          response = Response.json({ status: 'ok', engine: 'RoadSearch', version: '1.0.0', time: new Date().toISOString() });
          break;

        case url.pathname === '/init':
          const seeded = await initDB(env.DB);
          response = Response.json({ ok: true, seeded });
          break;

        case url.pathname === '/search' || url.pathname === '/api/search':
          response = await handleSearch(request, env);
          break;

        case url.pathname === '/suggest':
          response = await handleSuggest(request, env);
          break;

        case url.pathname === '/stats':
          response = await handleStats(env);
          break;

        case url.pathname === '/lucky':
          return await handleLucky(request, env);

        case request.method === 'POST' && url.pathname === '/index':
          response = await handleIndex(request, env);
          break;

        default:
          response = Response.json({
            engine: 'RoadSearch',
            version: '1.0.0',
            endpoints: {
              search: 'GET /search?q=query&category=&domain=&page=1&limit=20&ai=true',
              suggest: 'GET /suggest?q=prefix',
              lucky: 'GET /lucky?q=query (redirects to top result)',
              stats: 'GET /stats',
              index: 'POST /index (auth required)',
              health: 'GET /health',
            },
            tagline: 'Search the Road. Find the Way.',
          });
      }
    } catch (err) {
      console.error('RoadSearch error:', err);
      response = Response.json({ error: err.message }, { status: 500 });
    }

    const h = new Headers(response.headers);
    for (const [k, v] of Object.entries(headers)) h.set(k, v);
    return new Response(response.body, { status: response.status, headers: h });
  },
};
