/**
 * Stage 1: VALIDATE
 *
 * Validates incoming feedback events:
 * 1. Schema validation via Zod
 * 2. Range validation (scores in bounds, timestamps sane)
 * 3. Deduplication (same modal + session = duplicate)
 */

import { FeedbackEventSchema, type FeedbackEvent } from "../types.js";
import type { ValidationResult } from "./types.js";

/** In-memory set of recently processed event IDs for deduplication */
const recentEventIds = new Set<string>();
const MAX_DEDUP_CACHE = 10000;

/**
 * Validate a raw feedback event against the schema and business rules.
 */
export function validateFeedback(raw: unknown): ValidationResult {
  // 1. Schema validation
  const parsed = FeedbackEventSchema.safeParse(raw);
  if (!parsed.success) {
    return {
      valid: false,
      error: {
        type: "schema",
        message: "Feedback event failed schema validation",
        details: parsed.error.issues.map((i) => ({
          path: i.path.join("."),
          message: i.message,
          code: i.code,
        })),
      },
    };
  }

  const event = parsed.data;

  // 2. Range validation — scores must be 1-10
  if (event.feedback.scores) {
    for (const score of event.feedback.scores) {
      if (score.score < 1 || score.score > 10) {
        return {
          valid: false,
          error: {
            type: "range",
            message: `Score ${score.score} for dimension "${score.dimension}" out of bounds [1, 10]`,
          },
        };
      }
    }
  }

  // 3. Timestamp sanity — not more than 1 hour in the future, not more than 30 days old
  const eventTime = new Date(event.timestamp).getTime();
  const now = Date.now();
  const oneHourFuture = now + 60 * 60 * 1000;
  const thirtyDaysAgo = now - 30 * 24 * 60 * 60 * 1000;

  if (eventTime > oneHourFuture) {
    return {
      valid: false,
      error: {
        type: "range",
        message: "Event timestamp is more than 1 hour in the future",
      },
    };
  }

  if (eventTime < thirtyDaysAgo) {
    return {
      valid: false,
      error: {
        type: "range",
        message: "Event timestamp is more than 30 days old",
      },
    };
  }

  // 4. Deduplication — check modal+session combo
  const dedupKey = `${event.sessionId}:${event.modalType}:${event.id}`;
  if (recentEventIds.has(dedupKey)) {
    return {
      valid: false,
      error: {
        type: "duplicate",
        message: "Duplicate feedback event (same session, modal, and ID)",
      },
    };
  }

  // Add to dedup cache, evict oldest if over limit
  recentEventIds.add(dedupKey);
  if (recentEventIds.size > MAX_DEDUP_CACHE) {
    const first = recentEventIds.values().next().value;
    if (first) recentEventIds.delete(first);
  }

  // 5. Decision validation — if rejected, severity should ideally be set
  // (soft validation — we allow it but could log a warning)

  return {
    valid: true,
    event,
  };
}

/**
 * Clear the deduplication cache (for testing).
 */
export function clearDedupCache(): void {
  recentEventIds.clear();
}
