import { fileURLToPath as __fileURLToPath } from 'url';
import { dirname as __pathDirname } from 'path';
const __filename = __fileURLToPath(import.meta.url);
const __dirname = __pathDirname(__filename);
import { execSync } from "child_process";
import * as fs from "fs";
import * as path from "path";
import * as os from "os";
import { logger } from "../core/monitoring/logger.js";
import { getAPISkill } from "./api-skill.js";
const API_PATTERNS = [
  // Direct API URLs
  {
    pattern: /https?:\/\/api\.([a-z0-9-]+)\.(com|io|dev|app|co)/,
    nameGroup: 1
  },
  // REST API paths in docs
  { pattern: /https?:\/\/([a-z0-9-]+)\.com\/api/, nameGroup: 1 },
  // Developer docs
  { pattern: /https?:\/\/developer\.([a-z0-9-]+)\.com/, nameGroup: 1 },
  // Docs subdomains
  { pattern: /https?:\/\/docs\.([a-z0-9-]+)\.(com|io|dev)/, nameGroup: 1 }
];
const KNOWN_SPECS = {
  github: "https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json",
  stripe: "https://raw.githubusercontent.com/stripe/openapi/master/openapi/spec3.json",
  twilio: "https://raw.githubusercontent.com/twilio/twilio-oai/main/spec/json/twilio_api_v2010.json",
  slack: "https://api.slack.com/specs/openapi/v2/slack_web.json",
  discord: "https://raw.githubusercontent.com/discord/discord-api-spec/main/specs/openapi.json",
  openai: "https://raw.githubusercontent.com/openai/openai-openapi/master/openapi.yaml",
  anthropic: "https://raw.githubusercontent.com/anthropics/anthropic-sdk-python/main/openapi.json",
  linear: "https://api.linear.app/graphql",
  // GraphQL, not REST
  notion: "https://raw.githubusercontent.com/NotionX/notion-sdk-js/main/openapi.json",
  vercel: "https://openapi.vercel.sh/",
  cloudflare: "https://raw.githubusercontent.com/cloudflare/api-schemas/main/openapi.json",
  // Google Cloud Platform - uses Google Discovery format
  gcp: "https://www.googleapis.com/discovery/v1/apis",
  "gcp-compute": "https://compute.googleapis.com/$discovery/rest?version=v1",
  "gcp-storage": "https://storage.googleapis.com/$discovery/rest?version=v1",
  "gcp-run": "https://run.googleapis.com/$discovery/rest?version=v2",
  "gcp-functions": "https://cloudfunctions.googleapis.com/$discovery/rest?version=v2",
  "gcp-bigquery": "https://bigquery.googleapis.com/$discovery/rest?version=v2",
  "gcp-aiplatform": "https://aiplatform.googleapis.com/$discovery/rest?version=v1",
  // Railway - GraphQL API
  railway: "https://backboard.railway.com/graphql/v2"
  // GraphQL endpoint
};
const KNOWN_BASES = {
  github: "https://api.github.com",
  stripe: "https://api.stripe.com",
  twilio: "https://api.twilio.com",
  slack: "https://slack.com/api",
  discord: "https://discord.com/api",
  openai: "https://api.openai.com",
  anthropic: "https://api.anthropic.com",
  linear: "https://api.linear.app",
  notion: "https://api.notion.com",
  vercel: "https://api.vercel.com",
  cloudflare: "https://api.cloudflare.com",
  // Google Cloud Platform
  gcp: "https://www.googleapis.com",
  "gcp-compute": "https://compute.googleapis.com",
  "gcp-storage": "https://storage.googleapis.com",
  "gcp-run": "https://run.googleapis.com",
  "gcp-functions": "https://cloudfunctions.googleapis.com",
  "gcp-bigquery": "https://bigquery.googleapis.com",
  "gcp-aiplatform": "https://aiplatform.googleapis.com",
  // Railway (GraphQL)
  railway: "https://backboard.railway.com/graphql/v2"
};
const API_TYPES = {
  railway: "graphql",
  linear: "graphql",
  gcp: "google-discovery",
  "gcp-compute": "google-discovery",
  "gcp-storage": "google-discovery",
  "gcp-run": "google-discovery",
  "gcp-functions": "google-discovery",
  "gcp-bigquery": "google-discovery",
  "gcp-aiplatform": "google-discovery"
};
class APIDiscoverySkill {
  discoveryLog;
  discoveredAPIs = /* @__PURE__ */ new Map();
  constructor() {
    this.discoveryLog = path.join(
      os.homedir(),
      ".stackmemory",
      "api-discovery.log"
    );
  }
  /**
   * Analyze a URL for potential API endpoints
   */
  analyzeUrl(url) {
    if (url.includes("googleapis.com")) {
      const gcpMatch = url.match(/https?:\/\/([a-z]+)\.googleapis\.com/);
      if (gcpMatch) {
        const service = gcpMatch[1];
        const name = `gcp-${service}`;
        return {
          name,
          baseUrl: `https://${service}.googleapis.com`,
          specUrl: KNOWN_SPECS[name] || `https://${service}.googleapis.com/$discovery/rest?version=v1`,
          source: "known",
          confidence: 0.95,
          apiType: "google-discovery"
        };
      }
    }
    if (url.includes("railway.com") || url.includes("railway.app")) {
      return {
        name: "railway",
        baseUrl: KNOWN_BASES["railway"],
        specUrl: KNOWN_SPECS["railway"],
        source: "known",
        confidence: 0.95,
        apiType: "graphql"
      };
    }
    for (const [name, baseUrl] of Object.entries(KNOWN_BASES)) {
      if (url.includes(name) || url.includes(baseUrl)) {
        return {
          name,
          baseUrl,
          specUrl: KNOWN_SPECS[name],
          source: "known",
          confidence: 0.95,
          apiType: API_TYPES[name] || "rest"
        };
      }
    }
    for (const { pattern, nameGroup } of API_PATTERNS) {
      const match = url.match(pattern);
      if (match) {
        const name = match[nameGroup].toLowerCase();
        const baseUrl = this.inferBaseUrl(url, name);
        return {
          name,
          baseUrl,
          source: "inferred",
          confidence: 0.7,
          apiType: "rest"
        };
      }
    }
    return null;
  }
  /**
   * Infer base URL from a discovered URL
   */
  inferBaseUrl(url, name) {
    const patterns = [
      `https://api.${name}.com`,
      `https://api.${name}.io`,
      `https://${name}.com/api`
    ];
    try {
      const urlObj = new URL(url);
      if (urlObj.hostname.startsWith("api.")) {
        return `${urlObj.protocol}//${urlObj.hostname}`;
      }
      if (urlObj.pathname.includes("/api")) {
        return `${urlObj.protocol}//${urlObj.hostname}/api`;
      }
      return `${urlObj.protocol}//${urlObj.hostname}`;
    } catch {
      return patterns[0];
    }
  }
  /**
   * Try to discover OpenAPI spec for a service
   */
  async discoverSpec(name, baseUrl) {
    if (KNOWN_SPECS[name]) {
      return KNOWN_SPECS[name];
    }
    const specPaths = [
      "/openapi.json",
      "/openapi.yaml",
      "/swagger.json",
      "/swagger.yaml",
      "/api-docs",
      "/v1/openapi.json",
      "/v2/openapi.json",
      "/docs/openapi.json",
      "/.well-known/openapi.json"
    ];
    for (const specPath of specPaths) {
      const specUrl = `${baseUrl}${specPath}`;
      try {
        execSync(`curl -sI --max-time 2 "${specUrl}" | grep -q "200 OK"`, {
          stdio: "pipe"
        });
        return specUrl;
      } catch {
      }
    }
    return null;
  }
  /**
   * Process a URL and auto-register if it's an API
   */
  async processUrl(url, autoRegister = true) {
    const discovered = this.analyzeUrl(url);
    if (!discovered) {
      return null;
    }
    if (this.discoveredAPIs.has(discovered.name)) {
      return this.discoveredAPIs.get(discovered.name);
    }
    if (!discovered.specUrl && discovered.source !== "known") {
      try {
        discovered.specUrl = await this.discoverSpec(discovered.name, discovered.baseUrl) || void 0;
      } catch {
      }
    }
    this.discoveredAPIs.set(discovered.name, discovered);
    this.logDiscovery(discovered, url);
    if (autoRegister && discovered.confidence >= 0.7) {
      await this.registerAPI(discovered);
    }
    return discovered;
  }
  /**
   * Register a discovered API
   */
  async registerAPI(api) {
    const skill = getAPISkill();
    try {
      const result = await skill.add(api.name, api.baseUrl, {
        spec: api.specUrl
      });
      if (result.success) {
        logger.info(`Auto-registered API: ${api.name}`);
        return true;
      }
    } catch (error) {
      logger.warn(`Failed to auto-register API ${api.name}:`, error);
    }
    return false;
  }
  /**
   * Log discovery for debugging
   */
  logDiscovery(api, sourceUrl) {
    const entry = {
      timestamp: (/* @__PURE__ */ new Date()).toISOString(),
      api,
      sourceUrl
    };
    try {
      const dir = path.dirname(this.discoveryLog);
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
      }
      fs.appendFileSync(this.discoveryLog, JSON.stringify(entry) + "\n");
    } catch (error) {
      logger.warn("Failed to log API discovery:", error);
    }
  }
  /**
   * Get all discovered APIs
   */
  getDiscoveredAPIs() {
    return Array.from(this.discoveredAPIs.values());
  }
  /**
   * Suggest API registration based on recent activity
   */
  async suggestFromContext(recentUrls) {
    const result = {
      discovered: [],
      registered: [],
      skipped: []
    };
    for (const url of recentUrls) {
      const discovered = await this.processUrl(url, false);
      if (discovered) {
        result.discovered.push(discovered);
        const skill = getAPISkill();
        const listResult = await skill.list();
        const existingAPIs = listResult.data || [];
        if (existingAPIs.some((api) => api.name === discovered.name)) {
          result.skipped.push(discovered.name);
        } else if (discovered.confidence >= 0.7) {
          const registered = await this.registerAPI(discovered);
          if (registered) {
            result.registered.push(discovered.name);
          }
        }
      }
    }
    return result;
  }
  /**
   * Get help text
   */
  getHelp() {
    const restAPIs = Object.keys(KNOWN_SPECS).filter(
      (s) => !API_TYPES[s] || API_TYPES[s] === "rest"
    );
    const graphqlAPIs = Object.keys(KNOWN_SPECS).filter(
      (s) => API_TYPES[s] === "graphql"
    );
    const gcpAPIs = Object.keys(KNOWN_SPECS).filter(
      (s) => API_TYPES[s] === "google-discovery"
    );
    return `
API Auto-Discovery

Automatically detects and registers APIs when you browse documentation.

REST APIs (OpenAPI specs):
${restAPIs.map((s) => `  - ${s}`).join("\n")}

GraphQL APIs:
${graphqlAPIs.map((s) => `  - ${s}`).join("\n")}

Google Cloud Platform (Discovery format):
${gcpAPIs.map((s) => `  - ${s}`).join("\n")}

How It Works:
1. Monitors URLs you access during development
2. Identifies API documentation and endpoints
3. Finds OpenAPI specs automatically
4. Registers APIs for easy access via /api exec

Usage:
  # Check if a URL is a known API
  stackmemory api discover <url>

  # List discovered APIs
  stackmemory api discovered

  # Register all discovered APIs
  stackmemory api register-discovered
`;
  }
}
let discoveryInstance = null;
function getAPIDiscovery() {
  if (!discoveryInstance) {
    discoveryInstance = new APIDiscoverySkill();
  }
  return discoveryInstance;
}
export {
  APIDiscoverySkill,
  getAPIDiscovery
};
//# sourceMappingURL=api-discovery.js.map
