import { z } from 'zod';

export const EvaluationSuiteStatusSchema = z.enum(['draft', 'active', 'archived']);
export const EvaluationRunStatusSchema = z.enum(['queued', 'running', 'completed', 'failed']);
export const EvaluationVerdictSchema = z.enum(['pass', 'fail', 'needs_review']);

export const EvaluationSuiteSchema = z.object({
  id: z.string().min(1),
  productId: z.string().min(1),
  agentId: z.string().min(1),
  name: z.string().min(1),
  description: z.string().optional(),
  status: EvaluationSuiteStatusSchema,
  passThreshold: z.number().min(0).max(1),
  targetVersion: z.number().int().positive().optional(),
  tags: z.array(z.string()).default([]),
  metadata: z.record(z.unknown()).optional(),
  createdBy: z.string().min(1),
  createdAt: z.string(),
  updatedAt: z.string(),
});

export type EvaluationSuiteDoc = z.infer<typeof EvaluationSuiteSchema> & {
  _ts?: number;
  _etag?: string;
};

export const EvaluationCaseSchema = z.object({
  id: z.string().min(1),
  suiteId: z.string().min(1),
  productId: z.string().min(1),
  name: z.string().min(1),
  input: z.record(z.unknown()),
  expectedOutput: z.record(z.unknown()).optional(),
  rubric: z.string().optional(),
  tags: z.array(z.string()).default([]),
  critical: z.boolean().default(false),
  createdAt: z.string(),
});

export type EvaluationCaseDoc = z.infer<typeof EvaluationCaseSchema> & {
  _ts?: number;
  _etag?: string;
};

export const EvaluationRunSchema = z.object({
  id: z.string().min(1),
  suiteId: z.string().min(1),
  agentId: z.string().min(1),
  productId: z.string().min(1),
  agentVersionId: z.string().min(1),
  agentVersion: z.number().int().positive(),
  status: EvaluationRunStatusSchema,
  verdict: EvaluationVerdictSchema.optional(),
  passThreshold: z.number().min(0).max(1),
  releaseGate: z.boolean().default(false),
  totalCases: z.number().int().min(0),
  passedCases: z.number().int().min(0).default(0),
  failedCases: z.number().int().min(0).default(0),
  score: z.number().min(0).max(1).optional(),
  triggeredBy: z.string().min(1),
  startedAt: z.string(),
  completedAt: z.string().optional(),
  summary: z.string().optional(),
  reviewRequired: z.boolean().default(false),
});

export type EvaluationRunDoc = z.infer<typeof EvaluationRunSchema> & {
  _ts?: number;
  _etag?: string;
};

export const EvaluationResultSchema = z.object({
  id: z.string().min(1),
  runId: z.string().min(1),
  caseId: z.string().min(1),
  productId: z.string().min(1),
  passed: z.boolean(),
  score: z.number().min(0).max(1).optional(),
  actualOutput: z.record(z.unknown()).optional(),
  notes: z.string().optional(),
  createdAt: z.string(),
});

export type EvaluationResultDoc = z.infer<typeof EvaluationResultSchema> & {
  _ts?: number;
  _etag?: string;
};

export const CreateEvaluationSuiteSchema = z.object({
  agentId: z.string().min(1),
  name: z.string().min(1),
  description: z.string().optional(),
  passThreshold: z.number().min(0).max(1).default(0.8),
  targetVersion: z.number().int().positive().optional(),
  tags: z.array(z.string()).default([]),
  metadata: z.record(z.unknown()).optional(),
});

export const UpdateEvaluationSuiteSchema = z.object({
  name: z.string().min(1).optional(),
  description: z.string().optional(),
  status: EvaluationSuiteStatusSchema.optional(),
  passThreshold: z.number().min(0).max(1).optional(),
  targetVersion: z.number().int().positive().optional(),
  tags: z.array(z.string()).optional(),
  metadata: z.record(z.unknown()).optional(),
});

export const CreateEvaluationCaseSchema = z.object({
  name: z.string().min(1),
  input: z.record(z.unknown()),
  expectedOutput: z.record(z.unknown()).optional(),
  rubric: z.string().optional(),
  tags: z.array(z.string()).default([]),
  critical: z.boolean().default(false),
});

export const CreateEvaluationRunSchema = z.object({
  agentVersionId: z.string().min(1).optional(),
  releaseGate: z.boolean().default(false),
});

export const RecordEvaluationResultsSchema = z.object({
  summary: z.string().optional(),
  results: z
    .array(
      z.object({
        caseId: z.string().min(1),
        passed: z.boolean(),
        score: z.number().min(0).max(1).optional(),
        actualOutput: z.record(z.unknown()).optional(),
        notes: z.string().optional(),
      })
    )
    .min(1),
});

export const ListEvaluationSuitesQuerySchema = z.object({
  agentId: z.string().min(1).optional(),
  status: EvaluationSuiteStatusSchema.optional(),
  limit: z.coerce.number().min(1).max(100).default(20),
});

export type ListEvaluationSuitesQuery = z.infer<typeof ListEvaluationSuitesQuerySchema>;
