import { NotFoundError } from '../../lib/errors.js';
import { getCollection } from '../../lib/datastore.js';
import type {
  EvaluationCaseDoc,
  EvaluationResultDoc,
  EvaluationRunDoc,
  EvaluationSuiteDoc,
  ListEvaluationSuitesQuery,
} from './types.js';

function suiteCollection() {
  return getCollection<EvaluationSuiteDoc>('agent_evaluation_suites', '/productId');
}

function caseCollection() {
  return getCollection<EvaluationCaseDoc>('agent_evaluation_cases', '/suiteId');
}

function runCollection() {
  return getCollection<EvaluationRunDoc>('agent_evaluation_runs', '/productId');
}

function resultCollection() {
  return getCollection<EvaluationResultDoc>('agent_evaluation_results', '/runId');
}

export async function createSuite(doc: EvaluationSuiteDoc): Promise<EvaluationSuiteDoc> {
  return suiteCollection().create(doc);
}

export async function listSuites(
  productId: string,
  query: ListEvaluationSuitesQuery
): Promise<EvaluationSuiteDoc[]> {
  return suiteCollection().findMany({
    filter: {
      productId,
      ...(query.agentId ? { agentId: query.agentId } : {}),
      ...(query.status ? { status: query.status } : {}),
    },
    sort: { createdAt: -1 },
    limit: query.limit,
  });
}

export async function getSuite(id: string, productId: string): Promise<EvaluationSuiteDoc> {
  const suite = await suiteCollection().findById(id, productId);
  if (!suite) throw new NotFoundError(`Evaluation suite '${id}' not found`);
  return suite;
}

export async function updateSuite(
  id: string,
  productId: string,
  updates: Partial<EvaluationSuiteDoc>
): Promise<EvaluationSuiteDoc> {
  const updated = await suiteCollection().update(id, productId, {
    ...updates,
    updatedAt: new Date().toISOString(),
  });
  if (!updated) throw new NotFoundError(`Evaluation suite '${id}' not found`);
  return updated;
}

export async function deleteSuite(id: string, productId: string): Promise<void> {
  await suiteCollection().delete(id, productId);
}

export async function createCase(doc: EvaluationCaseDoc): Promise<EvaluationCaseDoc> {
  return caseCollection().create(doc);
}

export async function listCases(suiteId: string): Promise<EvaluationCaseDoc[]> {
  return caseCollection().findMany({
    filter: { suiteId },
    sort: { createdAt: 1 },
    limit: 500,
  });
}

export async function createRun(doc: EvaluationRunDoc): Promise<EvaluationRunDoc> {
  return runCollection().create(doc);
}

export async function getRun(id: string, productId: string): Promise<EvaluationRunDoc> {
  const run = await runCollection().findById(id, productId);
  if (!run) throw new NotFoundError(`Evaluation run '${id}' not found`);
  return run;
}

export async function updateRun(id: string, productId: string, updates: Partial<EvaluationRunDoc>) {
  const updated = await runCollection().update(id, productId, updates);
  if (!updated) throw new NotFoundError(`Evaluation run '${id}' not found`);
  return updated;
}

export async function createResults(docs: EvaluationResultDoc[]): Promise<EvaluationResultDoc[]> {
  const writes = docs.map(doc => resultCollection().create(doc));
  return Promise.all(writes);
}

export async function listResults(runId: string): Promise<EvaluationResultDoc[]> {
  return resultCollection().findMany({
    filter: { runId },
    sort: { createdAt: 1 },
    limit: 1000,
  });
}

export async function listRunsBySuite(
  productId: string,
  suiteId: string,
  limit = 50
): Promise<EvaluationRunDoc[]> {
  return runCollection().findMany({
    filter: { productId, suiteId },
    sort: { startedAt: -1 },
    limit,
  });
}

export async function listRunsByAgent(
  productId: string,
  agentId: string,
  limit = 50
): Promise<EvaluationRunDoc[]> {
  return runCollection().findMany({
    filter: { productId, agentId },
    sort: { startedAt: -1 },
    limit,
  });
}
