/**
 * GooseFactory Learning System — Core Type Definitions + Zod Schemas
 *
 * Every feedback type from §3 and §6 of CONTRACTS.md is defined here
 * with both TypeScript interfaces and Zod schemas for runtime validation.
 */

import { z } from "zod";

// ═══════════════════════════════════════════════════════════════
// ENUMS & LITERALS
// ═══════════════════════════════════════════════════════════════

export const QualityDimensionEnum = z.enum([
  "code_quality",
  "design_aesthetics",
  "design_ux",
  "test_coverage",
  "documentation",
  "architecture",
  "error_handling",
  "performance",
  "security",
  "creativity",
  "completeness",
  "naming",
  "dx",
]);
export type QualityDimension = z.infer<typeof QualityDimensionEnum>;

export const PipelineStageEnum = z.enum([
  "intake",
  "scaffolding",
  "building",
  "testing",
  "review",
  "staging",
  "production",
  "published",
]);
export type PipelineStage = z.infer<typeof PipelineStageEnum>;

export const WorkProductTypeEnum = z.enum([
  "mcp_server",
  "code_module",
  "design",
  "test_suite",
  "documentation",
  "pipeline_config",
]);
export type WorkProductType = z.infer<typeof WorkProductTypeEnum>;

export const DecisionValueEnum = z.enum([
  "approved",
  "rejected",
  "needs_work",
  "deferred",
  "skipped",
]);
export type DecisionValue = z.infer<typeof DecisionValueEnum>;

export const SeverityEnum = z.enum(["minor", "moderate", "major", "critical"]);
export type Severity = z.infer<typeof SeverityEnum>;

export const AnnotationTypeEnum = z.enum([
  "praise",
  "criticism",
  "question",
  "suggestion",
]);
export type AnnotationType = z.infer<typeof AnnotationTypeEnum>;

export const AnnotationSeverityEnum = z.enum([
  "nit",
  "minor",
  "major",
  "critical",
]);
export type AnnotationSeverity = z.infer<typeof AnnotationSeverityEnum>;

export const ConfidenceZoneEnum = z.enum([
  "guess",
  "educated_guess",
  "confident",
  "certain",
]);
export type ConfidenceZone = z.infer<typeof ConfidenceZoneEnum>;

export const PreferenceEnum = z.enum(["A", "B", "neither", "both_good"]);
export type Preference = z.infer<typeof PreferenceEnum>;

export const PreferenceStrengthEnum = z.enum([
  "slight",
  "moderate",
  "strong",
  "overwhelming",
]);
export type PreferenceStrength = z.infer<typeof PreferenceStrengthEnum>;

export const DeviceTypeEnum = z.enum(["desktop", "mobile"]);
export type DeviceType = z.infer<typeof DeviceTypeEnum>;

export const TimeOfDayEnum = z.enum([
  "morning",
  "afternoon",
  "evening",
  "night",
]);
export type TimeOfDay = z.infer<typeof TimeOfDayEnum>;

// ═══════════════════════════════════════════════════════════════
// WORK PRODUCT REF — What was reviewed
// ═══════════════════════════════════════════════════════════════

export const GenerationContextSchema = z.object({
  promptHash: z.string(),
  memorySnapshot: z.array(z.string()),
  modelUsed: z.string(),
  generationTimeMs: z.number().nonnegative(),
  iterationCount: z.number().int().nonnegative(),
});
export type GenerationContext = z.infer<typeof GenerationContextSchema>;

export const WorkProductRefSchema = z.object({
  type: WorkProductTypeEnum,
  id: z.string().min(1),
  version: z.string().min(1),
  path: z.string().optional(),
  summary: z.string(),
  bubaConfidence: z.number().min(0).max(1),
  bubaScorePrediction: z.number().min(1).max(10).optional(),
  generationContext: GenerationContextSchema,
});
export type WorkProductRef = z.infer<typeof WorkProductRefSchema>;

// ═══════════════════════════════════════════════════════════════
// DECISION FEEDBACK — Approve / Reject / Needs Work
// ═══════════════════════════════════════════════════════════════

export const DecisionFeedbackSchema = z.object({
  decision: DecisionValueEnum,
  reason: z.string().optional(),
  severity: SeverityEnum.optional(),
  blockers: z.array(z.string()).optional(),
  suggestions: z.array(z.string()).optional(),
  tags: z.array(z.string()).optional(),
});
export type DecisionFeedback = z.infer<typeof DecisionFeedbackSchema>;

// ═══════════════════════════════════════════════════════════════
// DIMENSION SCORE — Per-axis quality ratings
// ═══════════════════════════════════════════════════════════════

export const DimensionScoreSchema = z.object({
  dimension: QualityDimensionEnum,
  score: z.number().min(1).max(10),
  weight: z.number().optional(),
  comment: z.string().optional(),
});
export type DimensionScore = z.infer<typeof DimensionScoreSchema>;

// ═══════════════════════════════════════════════════════════════
// FREE TEXT FEEDBACK — Written praise & criticism
// ═══════════════════════════════════════════════════════════════

export const FreeTextFeedbackSchema = z.object({
  liked: z.string().optional(),
  disliked: z.string().optional(),
  generalNotes: z.string().optional(),
});
export type FreeTextFeedback = z.infer<typeof FreeTextFeedbackSchema>;

// ═══════════════════════════════════════════════════════════════
// COMPARISON FEEDBACK — A vs B preferences
// ═══════════════════════════════════════════════════════════════

export const ComparisonFeedbackSchema = z.object({
  preferred: PreferenceEnum,
  reason: z.string().optional(),
  preferenceStrength: PreferenceStrengthEnum,
  winningFactors: z.array(z.string()).optional(),
  perDimension: z
    .array(
      z.object({
        dimension: QualityDimensionEnum,
        winner: z.enum(["A", "B", "tie"]),
      })
    )
    .optional(),
  timeOnA_ms: z.number().nonnegative().optional(),
  timeOnB_ms: z.number().nonnegative().optional(),
});
export type ComparisonFeedback = z.infer<typeof ComparisonFeedbackSchema>;

// ═══════════════════════════════════════════════════════════════
// ANNOTATION — Specific region feedback
// ═══════════════════════════════════════════════════════════════

export const AnnotationTargetSchema = z.object({
  file: z.string().optional(),
  lineStart: z.number().int().optional(),
  lineEnd: z.number().int().optional(),
  charStart: z.number().int().optional(),
  charEnd: z.number().int().optional(),
  selector: z.string().optional(),
  region: z.string().optional(),
});
export type AnnotationTarget = z.infer<typeof AnnotationTargetSchema>;

export const AnnotationSchema = z.object({
  type: AnnotationTypeEnum,
  target: AnnotationTargetSchema,
  text: z.string(),
  severity: AnnotationSeverityEnum.optional(),
  category: z.string().optional(),
});
export type Annotation = z.infer<typeof AnnotationSchema>;

// ═══════════════════════════════════════════════════════════════
// CONFIDENCE FEEDBACK — Certainty level
// ═══════════════════════════════════════════════════════════════

export const ConfidenceFeedbackSchema = z.object({
  confidencePercent: z.number().min(0).max(100),
  zone: ConfidenceZoneEnum,
  wouldDelegateToAI: z.boolean(),
  needsExpertReview: z.boolean(),
  lowConfidenceReason: z.string().optional(),
  isTrainingExample: z.boolean().optional(),
});
export type ConfidenceFeedback = z.infer<typeof ConfidenceFeedbackSchema>;

// ═══════════════════════════════════════════════════════════════
// ESTIMATION FEEDBACK
// ═══════════════════════════════════════════════════════════════

export const EstimationFeedbackSchema = z.object({
  estimate: z.union([z.number(), z.literal("unknown"), z.literal("break")]),
  context: z.string().optional(),
  hoveredValues: z.array(z.number()).optional(),
});
export type EstimationFeedback = z.infer<typeof EstimationFeedbackSchema>;

// ═══════════════════════════════════════════════════════════════
// BATCH DECISION
// ═══════════════════════════════════════════════════════════════

export const BatchDecisionSchema = z.object({
  itemId: z.string(),
  decision: z.enum(["approve", "reject", "love", "skip"]),
  timeMs: z.number().nonnegative(),
  flippedForDetails: z.boolean(),
});
export type BatchDecision = z.infer<typeof BatchDecisionSchema>;

// ═══════════════════════════════════════════════════════════════
// COMPOSITE FEEDBACK TYPES
// ═══════════════════════════════════════════════════════════════

export const RetrospectiveNoteSchema = z.object({
  text: z.string(),
  priority: z.enum(["urgent", "important", "idea"]).optional(),
});

export const RetrospectiveFeedbackSchema = z.object({
  start: z.array(RetrospectiveNoteSchema),
  stop: z.array(RetrospectiveNoteSchema),
  continue_: z.array(RetrospectiveNoteSchema),
});
export type RetrospectiveFeedback = z.infer<typeof RetrospectiveFeedbackSchema>;

export const RankingFeedbackSchema = z.object({
  finalRanking: z.array(z.string()),
  rankingChanges: z.number().int().nonnegative(),
  lockedItems: z.array(z.string()),
  expandedItems: z.array(z.string()),
  perItemNotes: z.record(z.string(), z.string()).optional(),
});
export type RankingFeedback = z.infer<typeof RankingFeedbackSchema>;

export const ChecklistFeedbackSchema = z.object({
  checks: z.record(z.string(), z.boolean()),
  notes: z.record(z.string(), z.string()),
  checkOrder: z.array(z.string()),
  allClear: z.boolean(),
  completionRate: z.number().min(0).max(1),
});
export type ChecklistFeedback = z.infer<typeof ChecklistFeedbackSchema>;

export const TemperatureFeedbackSchema = z.object({
  temperature: z.number().min(0).max(100),
  zone: z.enum([
    "freezing",
    "cold",
    "lukewarm",
    "warm",
    "hot",
    "blazing",
  ]),
  drivers: z.array(z.string()),
  dragJourney: z.array(z.number()),
});
export type TemperatureFeedback = z.infer<typeof TemperatureFeedbackSchema>;

// ═══════════════════════════════════════════════════════════════
// FEEDBACK PAYLOAD — Union of all feedback types
// ═══════════════════════════════════════════════════════════════

export const FeedbackPayloadSchema = z.object({
  decision: DecisionFeedbackSchema.optional(),
  scores: z.array(DimensionScoreSchema).optional(),
  freeText: FreeTextFeedbackSchema.optional(),
  comparison: ComparisonFeedbackSchema.optional(),
  annotations: z.array(AnnotationSchema).optional(),
  confidence: ConfidenceFeedbackSchema.optional(),
  estimation: EstimationFeedbackSchema.optional(),
  batchDecisions: z.array(BatchDecisionSchema).optional(),
  retrospective: RetrospectiveFeedbackSchema.optional(),
  ranking: RankingFeedbackSchema.optional(),
  checklist: ChecklistFeedbackSchema.optional(),
  temperature: TemperatureFeedbackSchema.optional(),
  custom: z.record(z.string(), z.unknown()).optional(),
});
export type FeedbackPayload = z.infer<typeof FeedbackPayloadSchema>;

// ═══════════════════════════════════════════════════════════════
// MODAL METRICS — Implicit behavioral signals
// ═══════════════════════════════════════════════════════════════

export const HoverEntrySchema = z.object({
  target: z.string(),
  durationMs: z.number().nonnegative(),
});

export const ModalMetricsSchema = z.object({
  timeToFirstInteractionMs: z.number().nonnegative(),
  timeToDecisionMs: z.number().nonnegative(),
  fieldsModified: z.array(z.string()),
  scrollDepth: z.number().min(0).max(1).optional(),
  revisits: z.number().int().nonnegative(),
  totalInteractions: z.number().int().nonnegative(),
  viewportSize: z.object({
    width: z.number(),
    height: z.number(),
  }),
  deviceType: DeviceTypeEnum,
  hoverJourney: z.array(HoverEntrySchema).optional(),
  hesitationPoints: z.array(HoverEntrySchema).optional(),
});
export type ModalMetrics = z.infer<typeof ModalMetricsSchema>;

// ═══════════════════════════════════════════════════════════════
// ENRICHED META — Added by the enrichment pipeline stage
// ═══════════════════════════════════════════════════════════════

export const EnrichedMetaSchema = z.object({
  timeOfDay: TimeOfDayEnum,
  dayOfWeek: z.string(),
  sessionFatigue: z.number().int().nonnegative(),
  concurrentModals: z.number().int().nonnegative(),
  extractedThemes: z.array(z.string()).optional(),
  sentiment: z.number().min(-1).max(1).optional(),
  actionableItems: z.array(z.string()).optional(),
  predictionDelta: z.number().optional(),
});
export type EnrichedMeta = z.infer<typeof EnrichedMetaSchema>;

// ═══════════════════════════════════════════════════════════════
// FEEDBACK META — Combined metrics + enriched data
// ═══════════════════════════════════════════════════════════════

export const FeedbackMetaSchema = ModalMetricsSchema.merge(
  EnrichedMetaSchema.partial()
);
export type FeedbackMeta = z.infer<typeof FeedbackMetaSchema>;

// ═══════════════════════════════════════════════════════════════
// FEEDBACK EVENT — The atomic unit of feedback
// ═══════════════════════════════════════════════════════════════

export const FeedbackEventSchema = z.object({
  // Identity
  id: z.string().min(1),
  timestamp: z.string().datetime({ offset: true }),
  sessionId: z.string().min(1),
  modalType: z.string().min(1),
  modalVersion: z.string().min(1),

  // What was reviewed
  workProduct: WorkProductRefSchema,
  pipelineId: z.string().nullable(),
  pipelineStage: PipelineStageEnum.nullable(),
  mcpServerType: z.string().optional(),

  // The feedback
  feedback: FeedbackPayloadSchema,

  // Behavioral metrics
  meta: FeedbackMetaSchema,
});
export type FeedbackEvent = z.infer<typeof FeedbackEventSchema>;

// ═══════════════════════════════════════════════════════════════
// ENRICHED FEEDBACK EVENT — Post-enrichment
// ═══════════════════════════════════════════════════════════════

export const EnrichedFeedbackEventSchema = FeedbackEventSchema.extend({
  _enriched: z.literal(true),
  _themes: z.array(z.string()).optional(),
  _sentiment: z.number().min(-1).max(1).optional(),
  _actionableItems: z.array(z.string()).optional(),
  _predictionDelta: z.number().optional(),
  _pipelineContext: z
    .object({
      stage: PipelineStageEnum,
      stagesCompleted: z.number().int().nonnegative(),
      totalDuration: z.number().nonnegative(),
    })
    .optional(),
});
export type EnrichedFeedbackEvent = z.infer<typeof EnrichedFeedbackEventSchema>;

// ═══════════════════════════════════════════════════════════════
// ANALYSIS RESULT TYPES (from §6.2)
// ═══════════════════════════════════════════════════════════════

export interface ApprovalPatterns {
  overall: {
    approvalRate: number;
    totalDecisions: number;
    avgTimeToDecisionMs: number;
  };
  byServerType: Record<
    string,
    {
      approved: number;
      rejected: number;
      needsWork: number;
      approvalRate: number;
    }
  >;
  byStage: Record<
    string,
    {
      approvalRate: number;
      avgTimeMs: number;
      count: number;
    }
  >;
}

export interface DimensionTrend {
  dimension: QualityDimension;
  avgScore: number;
  trend: "improving" | "stable" | "declining";
  trendDelta: number;
  dataPoints: number;
  minimumThreshold?: number;
}

export interface ThemeCluster {
  theme: string;
  occurrences: number;
  avgSeverity: number;
  lastSeen: string;
  relatedDimensions: QualityDimension[];
  exampleFeedback: string[];
}

export interface Anomaly {
  type:
    | "approval_rate_drop"
    | "score_spike"
    | "new_rejection_pattern"
    | "calibration_drift";
  description: string;
  severity: "info" | "warning" | "critical";
  data: Record<string, unknown>;
  detectedAt: string;
}

export interface CandidateRule {
  rule: string;
  promptInstruction: string;
  confidence: number;
  occurrences: number;
  source:
    | "feedback_pattern"
    | "rejection_analysis"
    | "comparison"
    | "annotation";
  domain: QualityDimension;
  appliesTo: string[];
}

export interface AnalysisResults {
  approvalPatterns: ApprovalPatterns;
  dimensionTrends: DimensionTrend[];
  themes: ThemeCluster[];
  calibration: CalibrationCurve;
  anomalies: Anomaly[];
  candidateRules: CandidateRule[];
}

// ═══════════════════════════════════════════════════════════════
// CALIBRATION TYPES (from §6.5)
// ═══════════════════════════════════════════════════════════════

export interface CalibrationBucket {
  rawConfidenceLow: number;
  rawConfidenceHigh: number;
  avgPredictedConfidence: number;
  avgActualApprovalRate: number;
  sampleCount: number;
  correctionDelta: number;
  calibratedConfidence: number;
}

export interface CalibrationCurve {
  lastUpdated: string;
  totalDataPoints: number;
  buckets: CalibrationBucket[];
  expectedCalibrationError: number;
}

// ═══════════════════════════════════════════════════════════════
// APPLY RESULT (from §6.2 Stage 5)
// ═══════════════════════════════════════════════════════════════

export interface ApplyResult {
  memoryFilesUpdated: string[];
  rulesAdded: CandidateRule[];
  thresholdsChanged: Array<{
    dimension: QualityDimension;
    oldThreshold: number;
    newThreshold: number;
  }>;
  autonomyLevelChanges: Array<{
    taskType: string;
    oldLevel: number;
    newLevel: number;
  }>;
}

// ═══════════════════════════════════════════════════════════════
// SELF-IMPROVEMENT TYPES
// ═══════════════════════════════════════════════════════════════

export interface SelfCheckViolation {
  rule: string;
  description: string;
  severity: "nit" | "minor" | "major" | "critical";
  autoFixable: boolean;
  suggestion: string;
}

export interface SelfCheckResult {
  passed: boolean;
  score: number;
  confidence: number;
  violations: SelfCheckViolation[];
  recommendations: string[];
}

export interface CalibrationEntry {
  taskType: string;
  predicted: { score: number; confidence: number };
  actual: { score: number; approved: boolean };
  delta: number;
  timestamp: string;
}

export interface PredictionResponse {
  predictedScore: number;
  calibratedConfidence: number;
  predictedDecision: "approve" | "reject" | "needs_work";
  decisionProbabilities: {
    approve: number;
    reject: number;
    needsWork: number;
  };
  riskFactors: string[];
  suggestedImprovements: string[];
}

// ═══════════════════════════════════════════════════════════════
// AUTONOMY / DIMINISHING REVIEW TYPES
// ═══════════════════════════════════════════════════════════════

export type AutonomyTier = 1 | 2 | 3 | 4 | 5;

export interface AutonomyLevel {
  taskType: string;
  currentTier: AutonomyTier;
  approvalRate: number;
  totalReviews: number;
  consecutiveApprovals: number;
  lastRegression: string | null;
  lastUpdated: string;
}

export const TIER_THRESHOLDS: Record<AutonomyTier, { minApprovals: number; minRate: number }> = {
  1: { minApprovals: 0, minRate: 0 },
  2: { minApprovals: 10, minRate: 0.80 },
  3: { minApprovals: 25, minRate: 0.85 },
  4: { minApprovals: 50, minRate: 0.90 },
  5: { minApprovals: 100, minRate: 0.95 },
};

export interface RegressionStatus {
  regressed: boolean;
  from?: AutonomyTier;
  to?: AutonomyTier;
  reason?: string;
}

// ═══════════════════════════════════════════════════════════════
// FEEDBACK STATS / KPI TYPES
// ═══════════════════════════════════════════════════════════════

export interface FeedbackStats {
  totalEvents: number;
  last30Days: {
    approvalRate: number;
    avgQualityScore: number;
    avgTimeToDecisionMs: number;
    predictionAccuracy: number;
    autoApproveRate: number;
    feedbackVolume: number;
  };
  trends: {
    approvalRate: "improving" | "stable" | "declining";
    qualityScore: "improving" | "stable" | "declining";
    decisionSpeed: "improving" | "stable" | "declining";
  };
  activeRules: number;
  autonomyLevels: Record<string, number>;
}

export interface KPISnapshot {
  timestamp: string;
  approvalRate: number;
  avgQualityScore: number;
  avgTimeToDecisionMs: number;
  predictionAccuracy: number;
  topImprovementAreas: string[];
  feedbackVolume: number;
  dimensionDistributions: Record<QualityDimension, { avg: number; min: number; max: number; count: number }>;
}
