/**
 * Feedback Query Engine
 *
 * Query stored feedback events by various criteria:
 * - Pipeline ID
 * - Pipeline stage
 * - Date range
 * - Decision type
 * - MCP server type
 * - Modal type
 * - Dimension
 */

import type {
  EnrichedFeedbackEvent,
  DecisionValue,
  PipelineStage,
  QualityDimension,
} from "../types.js";
import { loadFeedbackEvents } from "./feedback-store.js";

// ═══════════════════════════════════════════════════════════════
// QUERY TYPES
// ═══════════════════════════════════════════════════════════════

export interface FeedbackQuery {
  /** Filter by pipeline ID */
  pipelineId?: string;
  /** Filter by pipeline stage */
  pipelineStage?: PipelineStage;
  /** Filter by decision type */
  decision?: DecisionValue;
  /** Filter by MCP server type */
  mcpServerType?: string;
  /** Filter by modal type */
  modalType?: string;
  /** Filter by start date (inclusive) */
  since?: Date;
  /** Filter by end date (inclusive) */
  until?: Date;
  /** Filter by minimum score on a dimension */
  minScore?: { dimension: QualityDimension; score: number };
  /** Filter by maximum score on a dimension */
  maxScore?: { dimension: QualityDimension; score: number };
  /** Filter events that have specific themes */
  themes?: string[];
  /** Limit number of results */
  limit?: number;
  /** Sort order */
  sort?: "asc" | "desc";
}

// ═══════════════════════════════════════════════════════════════
// QUERY ENGINE
// ═══════════════════════════════════════════════════════════════

/**
 * Query feedback events with flexible filters.
 */
export async function queryFeedback(
  dataDir: string,
  query: FeedbackQuery
): Promise<EnrichedFeedbackEvent[]> {
  // Determine how many days of data to load
  const days = query.since
    ? Math.ceil(
        (Date.now() - query.since.getTime()) / (24 * 60 * 60 * 1000)
      ) + 1
    : 90; // Default to 90 days

  const allEvents = await loadFeedbackEvents(dataDir, days);
  let filtered = allEvents;

  // Apply filters
  if (query.pipelineId) {
    filtered = filtered.filter((e) => e.pipelineId === query.pipelineId);
  }

  if (query.pipelineStage) {
    filtered = filtered.filter(
      (e) => e.pipelineStage === query.pipelineStage
    );
  }

  if (query.decision) {
    filtered = filtered.filter(
      (e) => e.feedback.decision?.decision === query.decision
    );
  }

  if (query.mcpServerType) {
    filtered = filtered.filter(
      (e) => e.mcpServerType === query.mcpServerType
    );
  }

  if (query.modalType) {
    filtered = filtered.filter((e) => e.modalType === query.modalType);
  }

  if (query.since) {
    const sinceMs = query.since.getTime();
    filtered = filtered.filter(
      (e) => new Date(e.timestamp).getTime() >= sinceMs
    );
  }

  if (query.until) {
    const untilMs = query.until.getTime();
    filtered = filtered.filter(
      (e) => new Date(e.timestamp).getTime() <= untilMs
    );
  }

  if (query.minScore) {
    const { dimension, score: minScore } = query.minScore;
    filtered = filtered.filter((e) => {
      const s = e.feedback.scores?.find((s) => s.dimension === dimension);
      return s !== undefined && s.score >= minScore;
    });
  }

  if (query.maxScore) {
    const { dimension, score: maxScore } = query.maxScore;
    filtered = filtered.filter((e) => {
      const s = e.feedback.scores?.find((s) => s.dimension === dimension);
      return s !== undefined && s.score <= maxScore;
    });
  }

  if (query.themes && query.themes.length > 0) {
    filtered = filtered.filter((e) => {
      const eventThemes = e._themes ?? [];
      return query.themes!.some((t) => eventThemes.includes(t));
    });
  }

  // Sort
  const sortMultiplier = query.sort === "asc" ? 1 : -1;
  filtered.sort(
    (a, b) =>
      sortMultiplier *
      (new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime())
  );

  // Limit
  if (query.limit) {
    filtered = filtered.slice(0, query.limit);
  }

  return filtered;
}

/**
 * Get all unique MCP server types from stored feedback.
 */
export async function getServerTypes(dataDir: string): Promise<string[]> {
  const events = await loadFeedbackEvents(dataDir, 365);
  const types = new Set<string>();
  for (const e of events) {
    if (e.mcpServerType) types.add(e.mcpServerType);
  }
  return [...types].sort();
}

/**
 * Get feedback events for a specific work product.
 */
export async function getFeedbackForWorkProduct(
  dataDir: string,
  workProductId: string
): Promise<EnrichedFeedbackEvent[]> {
  const events = await loadFeedbackEvents(dataDir, 365);
  return events.filter((e) => e.workProduct.id === workProductId);
}
