/**
 * Performance Monitoring MCP Tools for WordPress Server
 * Provides comprehensive performance insights and management
 */

import type { ToolDefinition } from "@/server/ToolRegistry.js";
import { PerformanceMonitor, type PerformanceMetrics } from "@/performance/PerformanceMonitor.js";
import { MetricsCollector } from "@/performance/MetricsCollector.js";
import {
  PerformanceAnalytics,
  type BenchmarkComparison,
  type PerformanceAnomaly,
} from "@/performance/PerformanceAnalytics.js";
import { toolWrapper } from "@/utils/toolWrapper.js";
import { ConfigHelpers } from "@/config/Config.js";
import { LoggerFactory } from "@/utils/logger.js";
import type { WordPressClient } from "@/client/api.js";

// Import helper functions
import {
  calculateHealthStatus,
  calculatePerformanceScore,
  calculateCacheEfficiency,
  formatUptime,
  parseTimeframe,
  processHistoricalDataForChart,
  calculateAverage,
  formatBenchmarkStatus,
  getBenchmarkImprovementDescription,
  calculateOverallRanking,
  formatAlertMessage,
  formatAnomalyDescription,
  calculateAlertStatus,
  formatPriority,
  formatEffort,
  calculateEstimatedImpact,
  convertToCSV,
  createSummaryReport,
  type PerformanceAlert,
} from "./PerformanceHelpers.js";

/**
 * Performance Tools Class
 * Provides MCP tools for WordPress performance monitoring
 */
export default class PerformanceTools {
  private monitor: PerformanceMonitor;
  private collector: MetricsCollector;
  private analytics: PerformanceAnalytics;
  private logger: ReturnType<typeof LoggerFactory.performance>;
  private historicalDataInterval?: NodeJS.Timeout | undefined;

  constructor(clients?: Map<string, unknown>) {
    // Initialize logger first
    this.logger = LoggerFactory.performance();

    // Initialize performance monitoring system
    this.monitor = new PerformanceMonitor({
      enableRealTimeMonitoring: true,
      enableHistoricalData: true,
      enableAlerts: true,
    });

    this.collector = new MetricsCollector(this.monitor, {
      enableRealTime: true,
      enableToolTracking: true,
      enableCacheIntegration: true,
    });

    this.analytics = new PerformanceAnalytics(this.collector, {
      enablePredictiveAnalysis: true,
      enableAnomalyDetection: true,
      enableTrendAnalysis: true,
    });

    // Register clients if provided
    if (clients) {
      for (const [siteId, client] of clients) {
        this.collector.registerClient(siteId, client);

        // Register cache manager if client has one
        const possibleCacheMgr = (client as Record<string, unknown>)?.cacheManager as unknown;
        if (possibleCacheMgr) {
          this.collector.registerCacheManager(siteId, possibleCacheMgr);
        }
      }
    }

    // Only start historical data collection in production environments
    if (ConfigHelpers.isProd() || ConfigHelpers.isDev()) {
      this.startHistoricalDataCollection();
    }
  }

  /**
   * Get all performance monitoring tools
   */
  getTools(): ToolDefinition[] {
    return [
      {
        name: "wp_performance_stats",
        description:
          "Get real-time performance statistics and metrics. " +
          "Note: Top-level metrics (totalRequests, averageResponseTime, errorRate) are session-wide aggregates across all sites. " +
          "Per-site cache and client stats are shown in the siteSpecific section when a site parameter is provided.",
        parameters: [
          {
            name: "site",
            type: "string",
            description: "Specific site ID for multi-site setups (optional for single site)",
            required: false,
          },
          {
            name: "category",
            type: "string",
            description: "Category of metrics to return (overview, requests, cache, system, tools, all)",
            required: false,
          },
          {
            name: "format",
            type: "string",
            description: "Detail level of the response (summary, detailed, raw)",
            required: false,
          },
        ],
        handler: this.getPerformanceStats.bind(this),
      },
      {
        name: "wp_performance_history",
        description: "Get historical performance data and trends",
        parameters: [
          {
            name: "site",
            type: "string",
            description: "Specific site ID for multi-site setups (optional for single site)",
            required: false,
          },
          {
            name: "timeframe",
            type: "string",
            description: "Time period for historical data (1h, 6h, 12h, 24h, 7d)",
            required: false,
          },
          {
            name: "metrics",
            type: "array",
            items: { type: "string" },
            description:
              "Specific metrics to include (responseTime, cacheHitRate, errorRate, memoryUsage, requestVolume)",
            required: false,
          },
          {
            name: "includeTrends",
            type: "boolean",
            description: "Include trend analysis (default: true)",
            required: false,
          },
        ],
        handler: this.getPerformanceHistory.bind(this),
      },
      {
        name: "wp_performance_benchmark",
        description:
          "Compare current performance against industry benchmarks. " +
          "Note: Benchmarks are based on session-wide aggregated metrics across all sites, not per-site metrics.",
        parameters: [
          {
            name: "site",
            type: "string",
            description: "Specific site ID for multi-site setups (optional for single site)",
            required: false,
          },
          {
            name: "category",
            type: "string",
            description: "Benchmark category (response_time, cache_performance, error_rate, system_resources, all)",
            required: false,
          },
          {
            name: "includeRecommendations",
            type: "boolean",
            description: "Include improvement recommendations (default: true)",
            required: false,
          },
        ],
        handler: this.getBenchmarkComparison.bind(this),
      },
      {
        name: "wp_performance_alerts",
        description: "Get performance alerts and anomaly detection results",
        parameters: [
          {
            name: "site",
            type: "string",
            description: "Specific site ID for multi-site setups (optional for single site)",
            required: false,
          },
          {
            name: "severity",
            type: "string",
            description: "Filter alerts by severity level (info, warning, error, critical)",
            required: false,
          },
          {
            name: "category",
            type: "string",
            description: "Filter alerts by category (performance, cache, system, wordpress)",
            required: false,
          },
          {
            name: "limit",
            type: "number",
            description: "Maximum number of alerts to return (default: 20)",
            required: false,
          },
          {
            name: "includeAnomalies",
            type: "boolean",
            description: "Include detected anomalies (default: true)",
            required: false,
          },
        ],
        handler: this.getPerformanceAlerts.bind(this),
      },
      {
        name: "wp_performance_optimize",
        description: "Get optimization recommendations and insights",
        parameters: [
          {
            name: "site",
            type: "string",
            description: "Specific site ID for multi-site setups (optional for single site)",
            required: false,
          },
          {
            name: "focus",
            type: "string",
            description: "Optimization focus area (speed, reliability, efficiency, scaling)",
            required: false,
          },
          {
            name: "priority",
            type: "string",
            description: "Implementation timeline (quick_wins, medium_term, long_term, all)",
            required: false,
          },
          {
            name: "includeROI",
            type: "boolean",
            description: "Include ROI estimates (default: true)",
            required: false,
          },
          {
            name: "includePredictions",
            type: "boolean",
            description: "Include performance predictions (default: true)",
            required: false,
          },
        ],
        handler: this.getOptimizationRecommendations.bind(this),
      },
      {
        name: "wp_performance_export",
        description: "Export comprehensive performance report",
        parameters: [
          {
            name: "site",
            type: "string",
            description: "Specific site ID for multi-site setups (optional for single site)",
            required: false,
          },
          {
            name: "format",
            type: "string",
            description: "Export format (json, csv, summary)",
            required: false,
          },
          {
            name: "includeHistorical",
            type: "boolean",
            description: "Include historical data (default: true)",
            required: false,
          },
          {
            name: "includeAnalytics",
            type: "boolean",
            description: "Include analytics and insights (default: true)",
            required: false,
          },
          {
            name: "timeRange",
            type: "string",
            description: "Time range for data export (1h, 6h, 24h, 7d, 30d)",
            required: false,
          },
        ],
        handler: this.exportPerformanceReport.bind(this),
      },
    ];
  }

  /**
   * Get real-time performance statistics
   */
  private async getPerformanceStats(_client: WordPressClient, params: Record<string, unknown>): Promise<unknown> {
    return toolWrapper(async () => {
      const {
        site,
        category = "overview",
        format = "summary",
      } = params as { site?: string; category?: string; format?: string };

      // Get current metrics
      const metrics = this.collector.collectCurrentMetrics();

      // Get site-specific metrics if requested
      let siteMetrics = null;
      if (site) {
        siteMetrics = this.collector.getSiteMetrics(site as string);
      }

      // Filter by category
      const result: Record<string, unknown> = {};

      if (category === "overview" || category === "all") {
        result.overview = {
          scope: site ? "session-wide (all sites combined)" : "session-wide",
          overallHealth: calculateHealthStatus(metrics),
          performanceScore: calculatePerformanceScore(metrics),
          totalRequests: metrics.requests.total,
          averageResponseTime: `${metrics.requests.averageResponseTime.toFixed(0)}ms`,
          cacheHitRate: `${(metrics.cache.hitRate * 100).toFixed(1)}%`,
          errorRate: `${((metrics.requests.failed / Math.max(metrics.requests.total, 1)) * 100).toFixed(2)}%`,
          uptime: formatUptime(metrics.system.uptime),
        };
      }

      if (category === "requests" || category === "all") {
        result.requests = {
          ...metrics.requests,
          requestsPerSecond: metrics.requests.requestsPerSecond.toFixed(2),
          p50ResponseTime: `${metrics.requests.p50ResponseTime}ms`,
          p95ResponseTime: `${metrics.requests.p95ResponseTime}ms`,
          p99ResponseTime: `${metrics.requests.p99ResponseTime}ms`,
        };
      }

      if (category === "cache" || category === "all") {
        result.cache = {
          ...metrics.cache,
          hitRate: `${(metrics.cache.hitRate * 100).toFixed(1)}%`,
          memoryUsage: `${metrics.cache.memoryUsageMB.toFixed(1)}MB`,
          efficiency: calculateCacheEfficiency(metrics.cache),
        };
      }

      if (category === "system" || category === "all") {
        result.system = {
          ...metrics.system,
          memoryUsage: `${metrics.system.memoryUsage}%`,
          cpuUsage: `${metrics.system.cpuUsage}%`,
          uptime: formatUptime(metrics.system.uptime),
        };
      }

      if (category === "tools" || category === "all") {
        result.tools = {
          mostUsedTool: metrics.tools.mostUsedTool,
          totalToolCalls: Object.values(metrics.tools.toolUsageCount).reduce(
            (sum: number, count: unknown) => sum + (typeof count === "number" ? count : 0),
            0,
          ),
          topTools: Object.entries(metrics.tools.toolUsageCount)
            .sort(([, a], [, b]) => (b as number) - (a as number))
            .slice(0, 5)
            .map(([tool, count]) => ({ tool, count })),
          toolPerformance: format === "detailed" ? metrics.tools.toolPerformance : undefined,
        };
      }

      // Add site-specific data if requested
      if (siteMetrics && siteMetrics.isActive) {
        result.siteSpecific = {
          siteId: site,
          cache: siteMetrics.cache,
          client: siteMetrics.client,
        };
      }

      // Add metadata
      result.metadata = {
        timestamp: new Date().toISOString(),
        category,
        format,
        site: site || "all",
        monitoringEnabled: true,
      };

      return {
        success: true,
        data: result,
      };
    });
  }

  /**
   * Get historical performance data and trends
   */
  private async getPerformanceHistory(_client: WordPressClient, params: Record<string, unknown>): Promise<unknown> {
    return toolWrapper(async () => {
      const {
        site,
        timeframe = "24h",
        metrics: requestedMetrics,
        includeTrends = true,
      } = params as {
        site?: string;
        timeframe?: string;
        metrics?: string[];
        includeTrends?: boolean;
      };

      // Convert timeframe to milliseconds
      const timeframMs = parseTimeframe(timeframe);
      const startTime = Date.now() - timeframMs;

      // Get historical data
      const historicalData = this.monitor.getHistoricalData(startTime);

      // Analyze trends if requested
      let trends = null;
      if (includeTrends) {
        // Add current data for trend analysis
        this.analytics.addDataPoint(this.collector.collectCurrentMetrics());
        trends = this.analytics.analyzeTrends();

        // Filter trends by requested metrics
        if (requestedMetrics && Array.isArray(requestedMetrics)) {
          trends = trends.filter((trend) => requestedMetrics.includes(trend.metric));
        }
      }

      // Process historical data for charting
      const chartData = processHistoricalDataForChart(historicalData, requestedMetrics as string[] | undefined);

      return {
        success: true,
        data: {
          timeframe,
          dataPoints: historicalData.length,
          historicalData: chartData,
          trends: trends || [],
          summary: {
            averageResponseTime: calculateAverage(historicalData.map((d) => d.requests.averageResponseTime)),
            averageCacheHitRate: calculateAverage(historicalData.map((d) => d.cache.hitRate)),
            averageErrorRate: calculateAverage(
              historicalData.map((d) => (d.requests.total > 0 ? d.requests.failed / d.requests.total : 0)),
            ),
            totalRequests: historicalData.reduce((sum, d) => sum + d.requests.total, 0),
          },
          metadata: {
            timestamp: new Date().toISOString(),
            site: site || "all",
            requestedMetrics: requestedMetrics || ["all"],
          },
        },
      };
    });
  }

  /**
   * Get benchmark comparison
   */
  private async getBenchmarkComparison(_client: WordPressClient, params: Record<string, unknown>): Promise<unknown> {
    const start = Date.now();
    this.logger.debug("performance benchmark: enter", { tool: "wp_performance_benchmark" });

    let timer: ReturnType<typeof setTimeout> | undefined;
    const timeoutPromise = new Promise<never>((_, reject) => {
      timer = setTimeout(() => reject(new Error("wp_performance_benchmark timed out after 5000ms")), 5000);
    });

    try {
      const result = await Promise.race([
        toolWrapper(async () => {
          const {
            site,
            category = "all",
            includeRecommendations = true,
          } = params as {
            site?: string;
            category?: string;
            includeRecommendations?: boolean;
          };

          // Get benchmark comparisons
          const benchmarks = this.analytics.benchmarkPerformance() as BenchmarkComparison[];

          // Filter by category if specified
          let filteredBenchmarks = benchmarks;
          if (category !== "all") {
            const categoryMap: Record<string, string> = {
              response_time: "Response Time",
              cache_performance: "Cache Hit Rate",
              error_rate: "Error Rate",
              system_resources: "Memory Usage",
            };
            const targetCategory = categoryMap[category as string];
            if (targetCategory) {
              filteredBenchmarks = benchmarks.filter((b) => b.category === targetCategory);
            }
          }

          // Get recommendations if requested
          let recommendations = null;
          if (includeRecommendations) {
            const insights = this.analytics.generateInsights();
            recommendations = insights
              .filter((insight) => insight.category === "optimization")
              .map((insight) => ({
                title: insight.title,
                description: insight.description,
                priority: insight.priority,
                estimatedImprovement: insight.estimatedImprovement,
                implementationEffort: insight.implementationEffort,
              }));
          }

          return {
            success: true,
            data: {
              benchmarks: filteredBenchmarks.map((benchmark) => ({
                ...benchmark,
                status: formatBenchmarkStatus(benchmark.status),
                improvement:
                  benchmark.improvement > 0
                    ? {
                        needed: benchmark.improvement,
                        description: getBenchmarkImprovementDescription(benchmark),
                      }
                    : null,
              })),
              overallRanking: calculateOverallRanking(benchmarks),
              recommendations: recommendations || [],
              metadata: {
                timestamp: new Date().toISOString(),
                category,
                site: site || "all",
                benchmarkVersion: "2024-industry-standards",
              },
            },
          };
        }),
        timeoutPromise,
      ]);

      this.logger.debug("performance benchmark: exit", {
        tool: "wp_performance_benchmark",
        durationMs: Date.now() - start,
      });
      return result;
    } catch (err) {
      this.logger.error("performance benchmark: failed", {
        tool: "wp_performance_benchmark",
        durationMs: Date.now() - start,
        error: err instanceof Error ? err.message : String(err),
      });
      return {
        success: false,
        status: "unavailable",
        error: err instanceof Error ? err.message : String(err),
        data: { benchmarks: [], recommendations: [], metadata: { timestamp: new Date().toISOString() } },
      };
    } finally {
      if (timer !== undefined) clearTimeout(timer);
    }
  }

  /**
   * Get performance alerts and anomalies
   */
  private async getPerformanceAlerts(_client: WordPressClient, params: Record<string, unknown>): Promise<unknown> {
    return toolWrapper(async () => {
      const {
        site,
        severity,
        category,
        limit = 20,
        includeAnomalies = true,
      } = params as {
        site?: string;
        severity?: string;
        category?: string;
        limit?: number;
        includeAnomalies?: boolean;
      };

      // Get alerts from monitor
      let alerts = this.monitor.getAlerts(severity) as PerformanceAlert[];

      // Filter by category if specified
      if (category) {
        alerts = alerts.filter((alert) => alert.category === category);
      }

      // Limit results
      alerts = alerts.slice(-(limit as number));

      // Get anomalies if requested
      let anomalies: PerformanceAnomaly[] = [];
      if (includeAnomalies) {
        anomalies = this.analytics.getAnomalies(severity) as PerformanceAnomaly[];
      }

      // Calculate alert summary
      const alertSummary = {
        total: alerts.length,
        critical: alerts.filter((a) => a.severity === "critical").length,
        error: alerts.filter((a) => a.severity === "error").length,
        warning: alerts.filter((a) => a.severity === "warning").length,
        info: alerts.filter((a) => a.severity === "info").length,
      };

      const anomalySummary = {
        total: anomalies.length,
        critical: anomalies.filter((a) => a.severity === "critical").length,
        major: anomalies.filter((a) => a.severity === "major").length,
        moderate: anomalies.filter((a) => a.severity === "moderate").length,
        minor: anomalies.filter((a) => a.severity === "minor").length,
      };

      return {
        success: true,
        data: {
          alerts: alerts.map((alert) => ({
            ...alert,
            timestamp: new Date(alert.timestamp).toISOString(),
            formattedMessage: formatAlertMessage(alert),
          })),
          anomalies: anomalies.map((anomaly) => ({
            ...anomaly,
            timestamp: new Date(anomaly.timestamp).toISOString(),
            formattedDescription: formatAnomalyDescription(anomaly),
          })),
          summary: {
            alerts: alertSummary,
            anomalies: anomalySummary,
            overallStatus: calculateAlertStatus(alertSummary, anomalySummary),
          },
          metadata: {
            timestamp: new Date().toISOString(),
            filters: { severity, category, site: site || "all" },
            limit,
          },
        },
      };
    });
  }

  /**
   * Get optimization recommendations
   */
  private async getOptimizationRecommendations(
    _client: WordPressClient,
    params: Record<string, unknown>,
  ): Promise<unknown> {
    return toolWrapper(async () => {
      const {
        site,
        focus = "speed",
        priority = "all",
        includeROI = true,
        includePredictions = true,
      } = params as {
        site?: string;
        focus?: string;
        priority?: string;
        includeROI?: boolean;
        includePredictions?: boolean;
      };

      // Generate optimization plan
      const optimizationPlan = this.analytics.generateOptimizationPlan();

      // Filter by priority
      let recommendations: Array<{
        priority: string;
        impact: string;
        implementationEffort: string;
        [key: string]: unknown;
      }> = [];
      if (priority === "quick_wins" || priority === "all") {
        recommendations.push(
          ...optimizationPlan.quickWins.map((r) => ({
            ...r,
            timeline: "quick_wins",
          })),
        );
      }
      if (priority === "medium_term" || priority === "all") {
        recommendations.push(
          ...optimizationPlan.mediumTerm.map((r) => ({
            ...r,
            timeline: "medium_term",
          })),
        );
      }
      if (priority === "long_term" || priority === "all") {
        recommendations.push(
          ...optimizationPlan.longTerm.map((r) => ({
            ...r,
            timeline: "long_term",
          })),
        );
      }

      // Filter by focus area
      if (focus !== "speed") {
        const focusMap: Record<string, string[]> = {
          reliability: ["reliability"],
          efficiency: ["cost", "performance"],
          scaling: ["performance", "reliability"],
        };
        const targetImpacts = focusMap[focus] || [];
        recommendations = recommendations.filter((r) => targetImpacts.includes(r.impact));
      }

      // Get predictions if requested
      let predictions: Record<string, unknown> | null = null;
      if (includePredictions) {
        predictions = this.analytics.predictPerformance(60); // 1 hour prediction
      }

      return {
        success: true,
        data: {
          recommendations: recommendations.map((rec) => ({
            ...rec,
            formattedPriority: formatPriority(rec.priority),
            formattedEffort: formatEffort(rec.implementationEffort),
          })),
          roi: includeROI ? optimizationPlan.estimatedROI : null,
          predictions: predictions || null,
          summary: {
            totalRecommendations: recommendations.length,
            quickWins: optimizationPlan.quickWins.length,
            mediumTerm: optimizationPlan.mediumTerm.length,
            longTerm: optimizationPlan.longTerm.length,
            estimatedImpact: calculateEstimatedImpact(recommendations),
          },
          metadata: {
            timestamp: new Date().toISOString(),
            focus,
            priority,
            site: site || "all",
          },
        },
      };
    });
  }

  /**
   * Export comprehensive performance report
   */
  private async exportPerformanceReport(_client: WordPressClient, params: Record<string, unknown>): Promise<unknown> {
    return toolWrapper(async () => {
      const {
        site,
        format = "json",
        includeHistorical = true,
        includeAnalytics = true,
        timeRange = "24h",
      } = params as {
        site?: string;
        format?: string;
        includeHistorical?: boolean;
        includeAnalytics?: boolean;
        timeRange?: string;
      };

      // Generate comprehensive analytics report
      const report = this.analytics.exportAnalyticsReport();

      // Add additional data based on parameters
      const exportData: {
        currentMetrics: PerformanceMetrics;
        [key: string]: unknown;
      } = {
        metadata: {
          generatedAt: new Date().toISOString(),
          site: site || "all",
          timeRange,
          format,
          version: "1.0.0",
        },
        summary: report.summary,
        currentMetrics: this.collector.collectCurrentMetrics(),
      };

      if (includeHistorical) {
        const timeframMs = parseTimeframe(timeRange);
        const startTime = Date.now() - timeframMs;
        exportData.historicalData = this.monitor.getHistoricalData(startTime);
      }

      if (includeAnalytics) {
        exportData.analytics = {
          trends: report.trends,
          benchmarks: report.benchmarks,
          insights: report.insights,
          anomalies: report.anomalies,
          predictions: report.predictions,
          optimizationPlan: report.optimizationPlan,
        };
      }

      // Add aggregated statistics
      exportData.aggregatedStats = {
        cache: this.collector.getAggregatedCacheStats(),
        client: this.collector.getAggregatedClientStats(),
      };

      // Add site comparison if multi-site
      if (!site) {
        exportData.siteComparison = this.collector.compareSitePerformance();
      }

      // Format output based on requested format
      let formattedOutput: unknown;
      if (format === "csv") {
        formattedOutput = convertToCSV(exportData);
      } else if (format === "summary") {
        formattedOutput = createSummaryReport(exportData);
      } else {
        formattedOutput = exportData;
      }

      return {
        success: true,
        data: formattedOutput,
        metadata: {
          timestamp: new Date().toISOString(),
          format,
          dataSize: JSON.stringify(exportData).length,
          site: site || "all",
        },
      };
    });
  }

  /**
   * Start historical data collection
   */
  private startHistoricalDataCollection(): void {
    // Skip in test environments to prevent performance issues
    if (ConfigHelpers.isTest() || ConfigHelpers.isCI()) {
      this.logger.debug("Skipping historical data collection in test/CI environment");
      return;
    }

    // Adjust collection frequency based on environment
    const interval = ConfigHelpers.isDev() ? 60000 : 30000; // 1 minute in dev, 30 seconds in prod

    this.logger.info("Starting historical data collection", {
      interval: `${interval / 1000}s`,
      environment: ConfigHelpers.get().get().app.nodeEnv,
    });

    this.historicalDataInterval = setInterval(() => {
      try {
        const currentMetrics = this.collector.collectCurrentMetrics();
        this.analytics.addDataPoint(currentMetrics);
        this.logger.debug("Historical metrics collected", {
          timestamp: new Date().toISOString(),
        });
      } catch (_error) {
        this.logger.error("Failed to collect historical metrics", {
          _error: _error instanceof Error ? _error.message : String(_error),
        });
      }
    }, interval);
  }

  /**
   * Stop historical data collection and cleanup resources
   */
  public destroy(): void {
    if (this.historicalDataInterval) {
      clearInterval(this.historicalDataInterval);
      this.historicalDataInterval = undefined;
      this.logger.info("Historical data collection stopped");
    }
  }
}
