import a from '../chunks/index5.mjs';
import { i as inquirer } from '../chunks/index6.mjs';
import { M as MCP_SERVICE_CONFIGS } from '../chunks/claude-config.mjs';
import { i18n } from '../chunks/index2.mjs';
import { d as displayInstalledMcpServices, b as isMcpServiceInstalled, i as installMcpService, u as uninstallMcpService } from './ccjk.CwGZSTAK.mjs';
import { existsSync, unlinkSync, statSync, mkdirSync, readFileSync } from 'node:fs';
import { homedir } from 'node:os';
import { CLOUD_ENDPOINTS } from '../chunks/constants.mjs';
import { writeFileAtomic } from '../chunks/fs-operations.mjs';
import { j as join } from './ccjk.bQ7Dh1g4.mjs';

const DEFAULT_API_URL = `${CLOUD_ENDPOINTS.MAIN.BASE_URL}${CLOUD_ENDPOINTS.MAIN.API_VERSION}/skills`;
const REQUEST_TIMEOUT = 3e4;
const MAX_RETRY_ATTEMPTS = 3;
const RETRY_DELAY = 1e3;
const DEFAULT_CACHE_TTL = 36e5;
const DEFAULT_THROTTLE_INTERVAL = 100;
const CACHE_VERSION = "1.0.0";
const CACHE_BASE_DIR = join(homedir(), ".ccjk", "mcp-marketplace", "cache");
class MarketplaceClient {
  baseUrl;
  apiKey;
  timeout;
  offlineMode;
  enableLogging;
  maxRetries;
  retryDelay;
  cacheTTL;
  enableDeduplication;
  throttleInterval;
  // In-memory cache
  memoryCache;
  // Pending requests for deduplication
  pendingRequests;
  // Last request timestamp for throttling
  lastRequestTime;
  // File-based cache
  cacheDir;
  cacheFile;
  constructor(options = {}) {
    this.baseUrl = options.baseUrl || DEFAULT_API_URL;
    this.apiKey = options.apiKey;
    this.timeout = options.timeout || REQUEST_TIMEOUT;
    this.offlineMode = options.offlineMode || false;
    this.enableLogging = options.enableLogging || false;
    this.maxRetries = options.maxRetries || MAX_RETRY_ATTEMPTS;
    this.retryDelay = options.retryDelay || RETRY_DELAY;
    this.cacheTTL = options.cacheTTL || DEFAULT_CACHE_TTL;
    this.enableDeduplication = options.enableDeduplication !== false;
    this.throttleInterval = options.throttleInterval || DEFAULT_THROTTLE_INTERVAL;
    this.memoryCache = /* @__PURE__ */ new Map();
    this.pendingRequests = /* @__PURE__ */ new Map();
    this.lastRequestTime = 0;
    this.cacheDir = CACHE_BASE_DIR;
    this.cacheFile = join(this.cacheDir, "marketplace.json");
  }
  // ==========================================================================
  // Public API Methods
  // ==========================================================================
  /**
   * Search packages with filters and sorting
   */
  async search(options = {}) {
    this.log("Searching packages with options:", options);
    const params = this.buildSearchParams(options);
    const response = await this.request("", {
      method: "GET",
      params
    });
    if (response.success && response.data) {
      return response.data;
    }
    return {
      packages: [],
      total: 0,
      page: options.page || 1,
      limit: options.limit || 20,
      totalPages: 0,
      hasMore: false
    };
  }
  /**
   * Get detailed information about a specific package
   */
  async getPackage(id) {
    this.log("Getting package:", id);
    const encodedId = encodeURIComponent(id);
    const response = await this.request(`/packages/${encodedId}`, {
      method: "GET"
    });
    return response.success && response.data ? response.data : null;
  }
  /**
   * Get version history for a package
   */
  async getVersions(id) {
    this.log("Getting versions for package:", id);
    const encodedId = encodeURIComponent(id);
    const response = await this.request(`/packages/${encodedId}/versions`, {
      method: "GET"
    });
    return response.success && response.data ? response.data : [];
  }
  /**
   * Get trending/popular packages
   */
  async getTrending(limit = 10) {
    this.log("Getting trending packages, limit:", limit);
    const response = await this.request("/trending", {
      method: "GET",
      params: { limit }
    });
    return response.success && response.data ? response.data : [];
  }
  /**
   * Get personalized recommendations based on installed packages
   */
  async getRecommendations(installed) {
    this.log("Getting recommendations for installed packages:", installed);
    const response = await this.request("/recommendations", {
      method: "POST",
      body: JSON.stringify({ installed })
    });
    return response.success && response.data ? response.data : [];
  }
  /**
   * Get all available categories
   */
  async getCategories() {
    this.log("Getting categories");
    const response = await this.request("/categories", {
      method: "GET"
    });
    return response.success && response.data ? response.data : [];
  }
  /**
   * Check for updates for installed packages
   */
  async checkUpdates(installed) {
    this.log("Checking updates for", installed.length, "packages");
    const response = await this.request("/updates/check", {
      method: "POST",
      body: JSON.stringify({ packages: installed })
    });
    return response.success && response.data ? response.data : [];
  }
  // ==========================================================================
  // Cache Management
  // ==========================================================================
  /**
   * Clear all cached data (memory and file)
   */
  clearCache() {
    this.memoryCache.clear();
    this.pendingRequests.clear();
    try {
      if (existsSync(this.cacheFile)) {
        unlinkSync(this.cacheFile);
      }
    } catch (error) {
      this.log("Failed to clear file cache:", error);
    }
    this.log("Cache cleared");
  }
  /**
   * Clear expired cache entries
   */
  clearExpiredCache() {
    const now = Date.now();
    const keysToDelete = [];
    this.memoryCache.forEach((entry, key) => {
      if (now - entry.timestamp > entry.ttl) {
        keysToDelete.push(key);
      }
    });
    keysToDelete.forEach((key) => this.memoryCache.delete(key));
    this.log("Cleared", keysToDelete.length, "expired cache entries");
  }
  /**
   * Get cache statistics
   */
  getCacheStats() {
    const fileCache = this.loadFileCache();
    let cacheSize = 0;
    try {
      if (existsSync(this.cacheFile)) {
        cacheSize = statSync(this.cacheFile).size;
      }
    } catch {
    }
    return {
      totalPackages: fileCache?.packages.length || 0,
      cacheSize,
      lastUpdated: fileCache?.lastUpdated || null,
      expiresAt: fileCache?.expiresAt || null,
      isExpired: this.isFileCacheExpired(),
      cachedCategories: fileCache?.categories.length || 0
    };
  }
  /**
   * Set offline mode
   */
  setOfflineMode(enabled) {
    this.offlineMode = enabled;
    this.log("Offline mode:", enabled ? "enabled" : "disabled");
  }
  // ==========================================================================
  // Private Request Methods
  // ==========================================================================
  /**
   * Make an HTTP request with caching, deduplication, and throttling
   */
  async request(endpoint, options = {}) {
    const url = this.buildUrl(endpoint, options.params);
    const cacheKey = `${options.method || "GET"}:${url}`;
    if (!options.skipCache && (options.method === "GET" || !options.method)) {
      const cached = this.getFromMemoryCache(cacheKey);
      if (cached) {
        this.log("Memory cache hit:", cacheKey);
        return {
          success: true,
          data: cached,
          timestamp: (/* @__PURE__ */ new Date()).toISOString()
        };
      }
    }
    if (this.enableDeduplication && (options.method === "GET" || !options.method)) {
      const pending = this.pendingRequests.get(cacheKey);
      if (pending) {
        this.log("Deduplicating request:", cacheKey);
        return pending.promise;
      }
    }
    if (this.offlineMode) {
      const cached = this.getFromMemoryCache(cacheKey);
      if (cached) {
        this.log("Offline mode: returning cached data");
        return {
          success: true,
          data: cached,
          timestamp: (/* @__PURE__ */ new Date()).toISOString()
        };
      }
      return {
        success: false,
        error: {
          code: "OFFLINE_MODE",
          message: "Offline mode enabled and no cached data available"
        },
        timestamp: (/* @__PURE__ */ new Date()).toISOString()
      };
    }
    await this.throttle();
    const requestPromise = this.executeRequest(url, options, cacheKey);
    if (this.enableDeduplication && (options.method === "GET" || !options.method)) {
      this.pendingRequests.set(cacheKey, {
        promise: requestPromise,
        timestamp: Date.now()
      });
      requestPromise.finally(() => {
        this.pendingRequests.delete(cacheKey);
      });
    }
    return requestPromise;
  }
  /**
   * Execute HTTP request with retry logic
   */
  async executeRequest(url, options, cacheKey) {
    let lastError = null;
    for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
      try {
        this.log(`Request attempt ${attempt}/${this.maxRetries}:`, url);
        const response = await this.makeRequest(url, options);
        if (response.success && response.data && (options.method === "GET" || !options.method)) {
          this.setMemoryCache(cacheKey, response.data, this.cacheTTL);
        }
        return response;
      } catch (error) {
        lastError = error instanceof Error ? error : new Error(String(error));
        this.log(`Request failed (attempt ${attempt}):`, lastError.message);
        if (lastError.name === "AbortError") {
          break;
        }
        if (attempt < this.maxRetries) {
          await this.sleep(this.retryDelay * attempt);
        }
      }
    }
    return {
      success: false,
      error: {
        code: "REQUEST_FAILED",
        message: lastError?.message || "Request failed after all retries"
      },
      timestamp: (/* @__PURE__ */ new Date()).toISOString()
    };
  }
  /**
   * Make a single HTTP request
   */
  async makeRequest(url, options) {
    const controller = new AbortController();
    const timeoutId = setTimeout(() => controller.abort(), this.timeout);
    try {
      const response = await fetch(url, {
        method: options.method || "GET",
        headers: this.getHeaders(),
        body: options.body,
        signal: controller.signal
      });
      clearTimeout(timeoutId);
      this.lastRequestTime = Date.now();
      const data = await response.json();
      if (!response.ok) {
        return {
          success: false,
          error: data.error || {
            code: `HTTP_${response.status}`,
            message: `HTTP ${response.status}: ${response.statusText}`
          },
          timestamp: (/* @__PURE__ */ new Date()).toISOString()
        };
      }
      return {
        ...data,
        success: true,
        timestamp: (/* @__PURE__ */ new Date()).toISOString()
      };
    } catch (error) {
      clearTimeout(timeoutId);
      if (error instanceof Error && error.name === "AbortError") {
        throw error;
      }
      return {
        success: false,
        error: {
          code: "NETWORK_ERROR",
          message: error instanceof Error ? error.message : String(error)
        },
        timestamp: (/* @__PURE__ */ new Date()).toISOString()
      };
    }
  }
  // ==========================================================================
  // Helper Methods
  // ==========================================================================
  /**
   * Build full URL with query parameters
   */
  buildUrl(endpoint, params) {
    const url = new URL(endpoint, this.baseUrl);
    if (params) {
      for (const [key, value] of Object.entries(params)) {
        if (value !== void 0 && value !== null) {
          if (Array.isArray(value)) {
            value.forEach((v) => url.searchParams.append(key, String(v)));
          } else {
            url.searchParams.append(key, String(value));
          }
        }
      }
    }
    return url.toString();
  }
  /**
   * Build search parameters from options
   */
  buildSearchParams(options) {
    return {
      keyword: options.query,
      category: options.category,
      tags: options.tags,
      sortBy: options.sortBy,
      sortOrder: options.sortOrder,
      verified: options.verified,
      verificationStatus: options.verificationStatus,
      author: options.author,
      platform: options.platform,
      codeTool: options.codeTool,
      minRating: options.minRating,
      page: options.page || 1,
      limit: options.limit || 20
    };
  }
  /**
   * Get request headers
   */
  getHeaders() {
    const headers = {
      "Content-Type": "application/json",
      "User-Agent": "CCJK-MCP-Marketplace-Client/1.0"
    };
    if (this.apiKey) {
      headers.Authorization = `Bearer ${this.apiKey}`;
    }
    return headers;
  }
  /**
   * Throttle requests
   */
  async throttle() {
    const now = Date.now();
    const elapsed = now - this.lastRequestTime;
    const remaining = this.throttleInterval - elapsed;
    if (remaining > 0) {
      await this.sleep(remaining);
    }
  }
  /**
   * Sleep for specified milliseconds
   */
  sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
  }
  /**
   * Log message (if logging is enabled)
   */
  log(...args) {
    if (this.enableLogging) {
      console.log("[MarketplaceClient]", ...args);
    }
  }
  // ==========================================================================
  // Memory Cache Methods
  // ==========================================================================
  /**
   * Get data from memory cache
   */
  getFromMemoryCache(key) {
    const entry = this.memoryCache.get(key);
    if (!entry) {
      return null;
    }
    const now = Date.now();
    if (now - entry.timestamp > entry.ttl) {
      this.memoryCache.delete(key);
      return null;
    }
    return entry.data;
  }
  /**
   * Set data in memory cache
   */
  setMemoryCache(key, data, ttl) {
    this.memoryCache.set(key, {
      data,
      timestamp: Date.now(),
      ttl
    });
  }
  // ==========================================================================
  // File Cache Methods
  // ==========================================================================
  /**
   * Ensure cache directory exists
   */
  ensureCacheDir() {
    if (!existsSync(this.cacheDir)) {
      mkdirSync(this.cacheDir, { recursive: true });
    }
  }
  /**
   * Load cache from file
   */
  loadFileCache() {
    try {
      if (!existsSync(this.cacheFile)) {
        return null;
      }
      const content = readFileSync(this.cacheFile, "utf-8");
      const cache = JSON.parse(content);
      if (cache.version !== CACHE_VERSION) {
        return null;
      }
      return cache;
    } catch {
      return null;
    }
  }
  /**
   * Save cache to file
   */
  saveFileCache(packages, categories) {
    try {
      this.ensureCacheDir();
      const now = (/* @__PURE__ */ new Date()).toISOString();
      const expiresAt = new Date(Date.now() + this.cacheTTL).toISOString();
      const cache = {
        version: CACHE_VERSION,
        packages,
        categories,
        createdAt: now,
        expiresAt,
        lastUpdated: now
      };
      writeFileAtomic(this.cacheFile, JSON.stringify(cache, null, 2), "utf-8");
    } catch (error) {
      this.log("Failed to save file cache:", error);
    }
  }
  /**
   * Check if file cache is expired
   */
  isFileCacheExpired() {
    const cache = this.loadFileCache();
    if (!cache) {
      return true;
    }
    const expiresAt = new Date(cache.expiresAt).getTime();
    return Date.now() >= expiresAt;
  }
}
let defaultClientInstance = null;
function getDefaultMarketplaceClient() {
  if (!defaultClientInstance) {
    defaultClientInstance = new MarketplaceClient();
  }
  return defaultClientInstance;
}

function getLocalFallbackServices() {
  return [
    // CCJK managed services (from mcp-services config)
    ...MCP_SERVICE_CONFIGS.map((svc) => ({
      name: svc.id,
      description: svc.id,
      // Will be replaced with i18n
      package: svc.config.command || svc.id,
      category: "ccjk",
      serviceId: svc.id,
      requiresApiKey: svc.requiresApiKey
    })),
    // External MCP servers from Awesome MCP Servers (fallback)
    { name: "Filesystem", description: "Secure file operations", package: "@modelcontextprotocol/server-filesystem", category: "core" },
    { name: "GitHub", description: "Repository management", package: "@modelcontextprotocol/server-github", category: "dev" },
    { name: "PostgreSQL", description: "Database operations", package: "@modelcontextprotocol/server-postgres", category: "database" },
    { name: "Puppeteer", description: "Browser automation", package: "@modelcontextprotocol/server-puppeteer", category: "automation" },
    { name: "Brave Search", description: "Web search", package: "@modelcontextprotocol/server-brave-search", category: "search" },
    { name: "Google Maps", description: "Location services", package: "@modelcontextprotocol/server-google-maps", category: "api" },
    { name: "Slack", description: "Team communication", package: "@modelcontextprotocol/server-slack", category: "communication" },
    { name: "Memory", description: "Knowledge graph", package: "@modelcontextprotocol/server-memory", category: "ai" }
  ];
}
function convertToMcpServer(pkg) {
  const lang = i18n.language;
  return {
    name: pkg.name,
    description: pkg.description[lang] || pkg.description.en,
    package: pkg.id,
    category: pkg.category,
    stars: pkg.rating,
    serviceId: pkg.id,
    requiresApiKey: pkg.permissions.some((p) => p.type === "env")
  };
}
async function mcpSearch(keyword, options = {}) {
  const client = getDefaultMarketplaceClient();
  try {
    const searchOptions = {
      query: keyword,
      category: options.category,
      verified: options.verified,
      sortBy: options.sortBy || "relevance",
      limit: options.limit || 50
    };
    const result = await client.search(searchOptions);
    if (result.packages.length === 0) {
      console.log(a.yellow(`
${i18n.t("mcp:market.noResults", { keyword })}`));
      return;
    }
    console.log(a.green.bold(`
${i18n.t("mcp:market.searchResults", { count: result.total, keyword })}
`));
    result.packages.forEach((pkg, idx) => {
      const lang = i18n.language;
      const verifiedBadge = pkg.verified ? a.green("\u2713") : a.dim("\u25CB");
      console.log(`${a.green(`${idx + 1}.`)} ${a.bold(pkg.name)} ${verifiedBadge} ${a.dim(`[${pkg.category}]`)}`);
      console.log(`   ${pkg.description[lang] || pkg.description.en}`);
      console.log(`   ${a.dim(`\u{1F4E5} ${pkg.downloads.toLocaleString()} | \u2B50 ${pkg.rating.toFixed(1)}/5.0`)}`);
      console.log(`   ${a.dim(pkg.id)}
`);
    });
    if (result.hasMore) {
      console.log(a.dim(`
${i18n.t("mcp:market.moreResults", { total: result.total, shown: result.packages.length })}`));
    }
  } catch {
    console.log(a.yellow(`
${i18n.t("mcp:market.apiUnavailable")}`));
    console.log(a.dim(i18n.t("mcp:market.usingLocalData")));
    const localServers = getLocalFallbackServices();
    const results = localServers.filter(
      (s) => s.name.toLowerCase().includes(keyword.toLowerCase()) || s.description.toLowerCase().includes(keyword.toLowerCase()) || s.category.toLowerCase().includes(keyword.toLowerCase())
    );
    if (results.length === 0) {
      console.log(a.yellow(`
${i18n.t("mcp:market.noResults", { keyword })}`));
      return;
    }
    console.log(a.green.bold(`
${i18n.t("mcp:market.searchResults", { count: results.length, keyword })}
`));
    results.forEach((server, idx) => {
      console.log(`${a.green(`${idx + 1}.`)} ${a.bold(server.name)} ${a.dim(`[${server.category}]`)}`);
      console.log(`   ${server.description}`);
      console.log(`   ${a.dim(server.package)}
`);
    });
  }
}
async function mcpTrending(options = {}) {
  const client = getDefaultMarketplaceClient();
  try {
    const trending = await client.getTrending(options.limit || 10);
    if (trending.length === 0) {
      console.log(a.yellow(`
${i18n.t("mcp:market.noTrending")}`));
      return;
    }
    console.log(a.green.bold(`
${i18n.t("mcp:market.trending")}
`));
    trending.forEach((pkg, idx) => {
      const lang = i18n.language;
      const verifiedBadge = pkg.verified ? a.green("\u2713") : a.dim("\u25CB");
      console.log(`${a.green(`${idx + 1}.`)} ${a.bold(pkg.name)} ${verifiedBadge} ${a.dim(`[${pkg.category}]`)}`);
      console.log(`   ${pkg.description[lang] || pkg.description.en}`);
      console.log(`   ${a.dim(`\u{1F4E5} ${pkg.downloads.toLocaleString()} | \u2B50 ${pkg.rating.toFixed(1)}/5.0 (${pkg.ratingCount} ${i18n.t("mcp:market.ratings")})`)}`);
      console.log(`   ${a.dim(pkg.id)}
`);
    });
  } catch {
    console.log(a.yellow(`
${i18n.t("mcp:market.apiUnavailable")}`));
    console.log(a.dim(i18n.t("mcp:market.usingLocalData")));
    console.log(a.green.bold(`
${i18n.t("mcp:market.trending")}
`));
    const localServers = getLocalFallbackServices();
    const trending = localServers.slice(0, options.limit || 5);
    trending.forEach((server, idx) => {
      console.log(`${a.green(`${idx + 1}.`)} ${a.bold(server.name)} ${a.dim(`[${server.category}]`)}`);
      console.log(`   ${server.description}`);
      console.log(`   ${a.dim(server.package)}
`);
    });
  }
}
async function mcpInstall(serverName, options = {}) {
  const client = getDefaultMarketplaceClient();
  let server = null;
  const localServers = getLocalFallbackServices();
  server = localServers.find((s) => s.name.toLowerCase() === serverName.toLowerCase()) || null;
  if (!server) {
    try {
      const pkg = await client.getPackage(serverName);
      if (pkg) {
        server = convertToMcpServer(pkg);
      }
    } catch {
    }
  }
  if (!server) {
    console.log(a.red(`
${i18n.t("mcp:market.serverNotFound", { name: serverName })}`));
    return;
  }
  if (server.serviceId) {
    const isInstalled = await isMcpServiceInstalled(server.serviceId, options.tool);
    if (isInstalled) {
      console.log(a.yellow(`
${i18n.t("mcp:installer.alreadyInstalled", { name: server.name })}`));
      return;
    }
    console.log(a.green(`
${i18n.t("mcp:market.installing", { name: server.name })}`));
    if (server.requiresApiKey) {
      console.log(a.dim(i18n.t("mcp:installer.requiresApiKey")));
    }
    console.log("");
    const { confirm } = await inquirer.prompt([{
      type: "confirm",
      name: "confirm",
      message: i18n.t("mcp:market.confirmInstall"),
      default: true
    }]);
    if (!confirm) {
      console.log(a.yellow(i18n.t("mcp:market.cancelled")));
      return;
    }
    const result = await installMcpService(server.serviceId, options.tool);
    if (result.success) {
      console.log(a.green(`
${i18n.t("mcp:market.installSuccess", { name: server.name })}`));
      console.log(a.dim(i18n.t("mcp:installer.restartRequired")));
    } else {
      console.log(a.red(`
${i18n.t("mcp:installer.installFailed", { name: server.name })}`));
      if (result.error) {
        console.log(a.dim(result.error));
      }
    }
  } else {
    console.log(a.green(`
${i18n.t("mcp:market.installing", { name: server.name })}`));
    console.log(a.dim(`Package: ${server.package}
`));
    const { confirm } = await inquirer.prompt([{
      type: "confirm",
      name: "confirm",
      message: i18n.t("mcp:market.confirmInstall"),
      default: true
    }]);
    if (!confirm) {
      console.log(a.yellow(i18n.t("mcp:market.cancelled")));
      return;
    }
    console.log(a.green(`
${i18n.t("mcp:market.installSuccess", { name: server.name })}`));
    console.log(a.dim(i18n.t("mcp:market.manualConfig")));
  }
}
async function mcpUninstall(serverName, options = {}) {
  const localServers = getLocalFallbackServices();
  const server = localServers.find((s) => s.name.toLowerCase() === serverName.toLowerCase());
  const serviceId = server?.serviceId || serverName;
  const isInstalled = await isMcpServiceInstalled(serviceId, options.tool);
  if (!isInstalled) {
    console.log(a.yellow(`
${i18n.t("mcp:installer.serviceNotInstalled", { id: serverName })}`));
    return;
  }
  const displayName = server?.name || serverName;
  const { confirm } = await inquirer.prompt([{
    type: "confirm",
    name: "confirm",
    message: i18n.t("mcp:market.confirmUninstall", { name: displayName }),
    default: false
  }]);
  if (!confirm) {
    console.log(a.yellow(i18n.t("mcp:market.cancelled")));
    return;
  }
  const result = await uninstallMcpService(serviceId, options.tool);
  if (result.success) {
    console.log(a.green(`
${i18n.t("mcp:installer.uninstallSuccess", { name: displayName })}`));
    console.log(a.dim(i18n.t("mcp:installer.restartRequired")));
  } else {
    console.log(a.red(`
${i18n.t("mcp:installer.uninstallFailed", { name: displayName })}`));
    if (result.error) {
      console.log(a.dim(result.error));
    }
  }
}
async function mcpList(options = {}) {
  await displayInstalledMcpServices(options.tool);
}

export { mcpList as a, mcpSearch as b, mcpUninstall as c, mcpTrending as d, mcpInstall as m };
