/* eslint-disable @typescript-eslint/no-unused-vars */
import type { ParsedQuery } from './query-parser.js';
import type {
  QueryIntent,
  ExtractedEntities,
  DiagnosticInsightDoc,
  ErrorClusterDoc,
} from './types.js';
import * as repository from './repository.js';
import { analyzeRootCause, generatePatternSummary } from './llm-analyzer.js';
import { aggregateClusterContext } from './telemetry-linking.js';

// ============================================================================
// Query Executor
// ============================================================================

export interface QueryExecutionResult {
  query: string;
  intent: QueryIntent;
  aiResponse: string;
  confidence: number;
  supportingData: Array<{
    type: 'cluster' | 'insight' | 'trend' | 'comparison' | 'session' | 'telemetry';
    id: string;
    title: string;
    relevanceScore: number;
    data?: Record<string, unknown>;
  }>;
  suggestedActions: string[];
  executionTimeMs: number;
}

interface ExecutionContext {
  productId?: string;
  userId: string;
}

/**
 * Executes a parsed query and generates results
 */
export async function executeQuery(
  parsedQuery: ParsedQuery,
  context: ExecutionContext
): Promise<QueryExecutionResult> {
  const startTime = Date.now();

  // Route to appropriate handler based on intent
  switch (parsedQuery.intent) {
    case 'root_cause':
      return await executeRootCauseQuery(parsedQuery, context, startTime);
    case 'pattern_search':
      return await executePatternSearchQuery(parsedQuery, context, startTime);
    case 'comparison':
      return await executeComparisonQuery(parsedQuery, context, startTime);
    case 'trend':
      return await executeTrendQuery(parsedQuery, context, startTime);
    case 'impact':
      return await executeImpactQuery(parsedQuery, context, startTime);
    default:
      return await executeGenericQuery(parsedQuery, context, startTime);
  }
}

// ============================================================================
// Intent-Specific Executors
// ============================================================================

async function executeRootCauseQuery(
  parsedQuery: ParsedQuery,
  context: ExecutionContext,
  startTime: number
): Promise<QueryExecutionResult> {
  const { entities } = parsedQuery;
  const productId = context.productId || entities.products?.[0];

  if (!productId) {
    return createErrorResult(parsedQuery, startTime, 'No product specified');
  }

  // Find relevant clusters
  const clusters = await repository.findClustersByProduct(productId, {
    status: 'active',
    limit: 10,
  });

  // Filter by error type if specified
  let relevantClusters = clusters;
  if (entities.errorTypes?.length) {
    relevantClusters = clusters.filter(c =>
      entities.errorTypes?.some(type => c.errorType.toLowerCase().includes(type.toLowerCase()))
    );
  }

  if (relevantClusters.length === 0) {
    return createEmptyResult(parsedQuery, startTime, 'No matching error clusters found');
  }

  // Get the most frequent cluster
  const topCluster = relevantClusters[0];

  // Check for existing insight
  const existingInsight = await repository.getLatestInsightForCluster(topCluster.id, productId);

  let aiResponse: string;
  const supportingData: QueryExecutionResult['supportingData'] = [];

  if (existingInsight) {
    aiResponse = formatInsightResponse(existingInsight);
    supportingData.push({
      type: 'insight',
      id: existingInsight.id,
      title: 'Pre-computed Analysis',
      relevanceScore: 0.9,
      data: existingInsight,
    });
  } else {
    // Generate new analysis
    const contextSummary = await aggregateClusterContext(topCluster, []);
    const analysis = await analyzeRootCause({
      cluster: topCluster,
      context: contextSummary,
      sampleStackTraces: [topCluster.stackSignature],
      relatedClusters: [],
      analysisType: 'root_cause',
    });

    aiResponse = analysis.hypothesis || 'Analysis pending additional data.';
    supportingData.push({
      type: 'cluster',
      id: topCluster.id,
      title: `${topCluster.errorType}: ${topCluster.occurrenceCount} occurrences`,
      relevanceScore: 1.0,
      data: topCluster,
    });
  }

  // Add related clusters
  for (const cluster of relevantClusters.slice(1, 4)) {
    supportingData.push({
      type: 'cluster',
      id: cluster.id,
      title: `${cluster.errorType}: ${cluster.occurrenceCount} occurrences`,
      relevanceScore: 0.7,
      data: cluster,
    });
  }

  return {
    query: parsedQuery.rawQuery,
    intent: 'root_cause',
    aiResponse,
    confidence: existingInsight?.confidenceScore || 0.6,
    supportingData,
    suggestedActions: existingInsight?.suggestedInvestigation || [
      'View cluster details',
      'Check related errors',
      'Review telemetry traces',
    ],
    executionTimeMs: Date.now() - startTime,
  };
}

async function executePatternSearchQuery(
  parsedQuery: ParsedQuery,
  context: ExecutionContext,
  startTime: number
): Promise<QueryExecutionResult> {
  const { entities } = parsedQuery;
  const productId = context.productId || entities.products?.[0];

  if (!productId) {
    return createErrorResult(parsedQuery, startTime, 'No product specified');
  }

  // Search clusters
  const clusters = await repository.findClustersByProduct(productId, {
    limit: 20,
  });

  // Filter by criteria
  let results = clusters;

  if (entities.errorTypes?.length) {
    results = results.filter(c =>
      entities.errorTypes?.some(type => c.errorType.toLowerCase().includes(type.toLowerCase()))
    );
  }

  if (entities.platforms?.length) {
    results = results.filter(c =>
      c.commonContext?.osVersions?.some(os =>
        entities.platforms?.some(p => os.version.toLowerCase().includes(p.toLowerCase()))
      )
    );
  }

  // Generate summaries
  const summaries = await Promise.all(
    results.slice(0, 5).map(async cluster => {
      const summary = await generatePatternSummary(cluster, {
        totalOccurrences: cluster.occurrenceCount,
        affectedUsers: [],
        timeRange: { start: cluster.firstSeenAt, end: cluster.lastSeenAt },
        mostCommonScreens: cluster.commonContext?.screenContexts || [],
        mostCommonActions: [],
        featureFlagCorrelations: [],
      });
      return { cluster, summary };
    })
  );

  const aiResponse =
    summaries.length > 0
      ? `Found ${results.length} matching error clusters:\n\n` +
        summaries
          .map(
            (s, i) =>
              `${i + 1}. **${s.cluster.errorType}** (${s.cluster.occurrenceCount} occurrences)\n   ${s.summary}`
          )
          .join('\n\n')
      : 'No matching error patterns found.';

  return {
    query: parsedQuery.rawQuery,
    intent: 'pattern_search',
    aiResponse,
    confidence: results.length > 0 ? 0.8 : 0.3,
    supportingData: results.slice(0, 5).map(cluster => ({
      type: 'cluster',
      id: cluster.id,
      title: cluster.errorType,
      relevanceScore: 0.8,
      data: cluster,
    })),
    suggestedActions: [
      'View cluster details',
      'Compare with historical data',
      'Filter by additional criteria',
    ],
    executionTimeMs: Date.now() - startTime,
  };
}

async function executeComparisonQuery(
  parsedQuery: ParsedQuery,
  context: ExecutionContext,
  startTime: number
): Promise<QueryExecutionResult> {
  const { entities } = parsedQuery;
  const productId = context.productId || entities.products?.[0];

  if (!productId) {
    return createErrorResult(parsedQuery, startTime, 'No product specified');
  }

  // Get recent clusters for comparison
  const clusters = await repository.findClustersByProduct(productId, {
    limit: 10,
  });

  if (clusters.length < 2) {
    return createEmptyResult(parsedQuery, startTime, 'Not enough clusters for comparison');
  }

  const clusterA = clusters[0];
  const clusterB = clusters[1];

  const aiResponse = `Comparing top 2 error clusters:

**${clusterA.errorType}** (${clusterA.occurrenceCount} occurrences)
- First seen: ${clusterA.firstSeenAt}
- Status: ${clusterA.status}
- Message pattern: ${clusterA.messageTemplate.slice(0, 100)}...

**${clusterB.errorType}** (${clusterB.occurrenceCount} occurrences)
- First seen: ${clusterB.firstSeenAt}
- Status: ${clusterB.status}
- Message pattern: ${clusterB.messageTemplate.slice(0, 100)}...

Key differences:
- ${clusterA.errorType !== clusterB.errorType ? 'Different error types' : 'Same error type'}
- ${Math.abs(clusterA.occurrenceCount - clusterB.occurrenceCount) > 10 ? 'Significant difference in occurrence count' : 'Similar occurrence rates'}
- ${clusterA.status !== clusterB.status ? 'Different resolution status' : 'Same status'}`;

  return {
    query: parsedQuery.rawQuery,
    intent: 'comparison',
    aiResponse,
    confidence: 0.7,
    supportingData: [
      {
        type: 'comparison',
        id: `${clusterA.id}_vs_${clusterB.id}`,
        title: 'Cluster Comparison',
        relevanceScore: 1.0,
        data: { clusterA, clusterB },
      },
    ],
    suggestedActions: [
      'View detailed comparison',
      'Compare with additional clusters',
      'Analyze temporal patterns',
    ],
    executionTimeMs: Date.now() - startTime,
  };
}

async function executeTrendQuery(
  parsedQuery: ParsedQuery,
  context: ExecutionContext,
  startTime: number
): Promise<QueryExecutionResult> {
  const { entities } = parsedQuery;
  const productId = context.productId || entities.products?.[0];

  if (!productId) {
    return createErrorResult(parsedQuery, startTime, 'No product specified');
  }

  const timeRange = entities.timeRange || {
    start: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString(),
    end: new Date().toISOString(),
  };

  // Get trends
  const trends = await repository.getClusterTrends(productId, {
    start: timeRange.start,
    end: timeRange.end,
  });

  const totalErrors = trends.reduce((sum, t) => sum + t.occurrenceCount, 0);
  const uniqueErrorTypes = new Set(trends.map(t => t.errorType)).size;

  const aiResponse = `Error trends for ${productId} (${timeRange.start.slice(0, 10)} to ${timeRange.end.slice(0, 10)}):

**Summary:**
- Total errors: ${totalErrors}
- Unique error types: ${uniqueErrorTypes}
- Most affected clusters: ${
    trends
      .slice(0, 3)
      .map(t => t.errorType)
      .join(', ') || 'N/A'
  }

**Top Clusters:**
${
  trends
    .slice(0, 5)
    .map(
      (t, i) =>
        `${i + 1}. ${t.errorType}: ${t.occurrenceCount} occurrences (${t.uniqueUsers} users)`
    )
    .join('\n') || 'No data available'
}

${trends.length > 0 && trends[0].occurrenceCount > trends[trends.length - 1]?.occurrenceCount * 2 ? '⚠️ Some errors are significantly more frequent than others.' : '✓ Error distribution appears balanced.'}`;

  return {
    query: parsedQuery.rawQuery,
    intent: 'trend',
    aiResponse,
    confidence: 0.75,
    supportingData: trends.slice(0, 5).map(trend => ({
      type: 'trend',
      id: trend.clusterId,
      title: `${trend.errorType}: ${trend.occurrenceCount}`,
      relevanceScore: 0.8,
      data: trend,
    })),
    suggestedActions: ['View trend chart', 'Compare with previous period', 'Export trend data'],
    executionTimeMs: Date.now() - startTime,
  };
}

async function executeImpactQuery(
  parsedQuery: ParsedQuery,
  context: ExecutionContext,
  startTime: number
): Promise<QueryExecutionResult> {
  const { entities } = parsedQuery;
  const productId = context.productId || entities.products?.[0];

  if (!productId) {
    return createErrorResult(parsedQuery, startTime, 'No product specified');
  }

  // Get active clusters
  const clusters = await repository.findClustersByProduct(productId, {
    status: 'active',
    limit: 20,
  });

  const totalAffectedUsers = clusters.reduce((sum, c) => sum + c.uniqueUsers, 0);
  const totalOccurrences = clusters.reduce((sum, c) => sum + c.occurrenceCount, 0);

  // Get top error types
  const topTypes = await repository.getTopErrorTypes(productId, 5);

  const aiResponse = `Error impact assessment for ${productId}:

**Overall Impact:**
- Active error clusters: ${clusters.length}
- Total occurrences: ${totalOccurrences}
- Estimated affected users: ${totalAffectedUsers}

**Top Error Types:**
${topTypes.map((t, i) => `${i + 1}. ${t.errorType}: ${t.count} clusters, ${t.totalOccurrences} total occurrences`).join('\n') || 'No data available'}

**Recommendations:**
${clusters.length > 5 ? '- Focus on the top 5 most frequent errors for maximum impact' : '- Review all active error clusters'}
${totalAffectedUsers > 100 ? '- High user impact: prioritize investigation' : '- Moderate user impact: scheduled review recommended'}`;

  return {
    query: parsedQuery.rawQuery,
    intent: 'impact',
    aiResponse,
    confidence: 0.8,
    supportingData: clusters.slice(0, 5).map(cluster => ({
      type: 'cluster',
      id: cluster.id,
      title: `${cluster.errorType} (${cluster.uniqueUsers} users)`,
      relevanceScore: 0.85,
      data: cluster,
    })),
    suggestedActions: [
      'View affected users',
      'Check severity breakdown',
      'Generate incident report',
    ],
    executionTimeMs: Date.now() - startTime,
  };
}

async function executeGenericQuery(
  parsedQuery: ParsedQuery,
  context: ExecutionContext,
  startTime: number
): Promise<QueryExecutionResult> {
  // Fallback for unhandled intents
  return {
    query: parsedQuery.rawQuery,
    intent: parsedQuery.intent,
    aiResponse:
      'I understand you want information about errors, but I need more specific details. Try asking:\n\n- "Why did [error type] occur?"\n- "Show me similar [error type] errors"\n- "How many users were affected by [issue]?"\n- "Compare error trends over time"',
    confidence: 0.3,
    supportingData: [],
    suggestedActions: ['View all error clusters', 'Search by error type', 'Browse by platform'],
    executionTimeMs: Date.now() - startTime,
  };
}

// ============================================================================
// Response Generation Helpers
// ============================================================================

function formatInsightResponse(insight: Partial<DiagnosticInsightDoc>): string {
  const parts: string[] = [];

  parts.push(`**Root Cause Category:** ${insight.rootCauseCategory || 'Unknown'}`);
  parts.push(
    `**Confidence:** ${insight.confidence || 'medium'} (${((insight.confidenceScore || 0) * 100).toFixed(0)}%)`
  );
  parts.push('');
  parts.push(`**Hypothesis:** ${insight.hypothesis || 'No hypothesis generated'}`);
  parts.push('');
  parts.push(
    `**Reasoning:** ${insight.reasoning || 'Analysis based on error patterns and telemetry data'}`
  );

  if (insight.evidence && insight.evidence.length > 0) {
    parts.push('');
    parts.push('**Evidence:**');
    for (const ev of insight.evidence) {
      parts.push(`- ${ev.type}: ${ev.description} (${ev.strength})`);
    }
  }

  if (insight.potentialFixDirection) {
    parts.push('');
    parts.push(`**Suggested Fix:** ${insight.potentialFixDirection}`);
  }

  return parts.join('\n');
}

function createErrorResult(
  parsedQuery: ParsedQuery,
  startTime: number,
  errorMessage: string
): QueryExecutionResult {
  return {
    query: parsedQuery.rawQuery,
    intent: parsedQuery.intent,
    aiResponse: `Unable to process query: ${errorMessage}. Please check your query and try again.`,
    confidence: 0,
    supportingData: [],
    suggestedActions: ['Check product ID', 'Verify time range', 'Simplify query'],
    executionTimeMs: Date.now() - startTime,
  };
}

function createEmptyResult(
  parsedQuery: ParsedQuery,
  startTime: number,
  message: string
): QueryExecutionResult {
  return {
    query: parsedQuery.rawQuery,
    intent: parsedQuery.intent,
    aiResponse: message,
    confidence: 0.3,
    supportingData: [],
    suggestedActions: ['Adjust search criteria', 'Expand time range', 'Try different keywords'],
    executionTimeMs: Date.now() - startTime,
  };
}
