import { openai, defaultModel, serviceOptions, supportsWebSearch, parseWithRetry } from '../agent.js';
import type { RetrievalCandidate, ValidatorOutput, MediaType } from '../types/agents.js';
import { z } from 'zod';
import { zodTextFormat } from 'openai/helpers/zod';

const ValidatorSchema = z.object({
  candidates: z.array(z.object({
    title: z.string(),
    reason: z.string(),
    isTrash: z.boolean(),
  })),
});

const CHUNK_SIZE = 30;

function splitIntoChunks<T>(items: T[], size: number): T[][] {
  const chunks: T[][] = [];
  for (let i = 0; i < items.length; i += size) {
    chunks.push(items.slice(i, i + size));
  }
  return chunks;
}

async function runValidatorChunk(
  candidates: RetrievalCandidate[],
  mediaLabel: string,
): Promise<ValidatorOutput> {
  const list = candidates.map((c) => `- ${c.title}: ${c.reason}`).join('\n');

  const response = await parseWithRetry(() => openai.responses.parse({
    model: defaultModel,
    temperature: 0.1,
    ...serviceOptions,
    ...(supportsWebSearch ? { tools: [{ type: 'web_search' as const }] } : {}),
    text: { format: zodTextFormat(ValidatorSchema, 'validation') },
    instructions: `You are a ${mediaLabel} metadata validator. For each candidate in the list, use web search to verify:
1. The title actually exists as a real, produced ${mediaLabel} (not a made-up or hallucinated title)
2. Correct the "reason" field with accurate metadata (actual genres, tone, year) if it contains errors

Set isTrash: true for entries that:
- Do not exist as a real ${mediaLabel}
- Are clearly hallucinated or fictional titles
- Are so incorrect that no real match can be identified

Set isTrash: false for real, verifiable ${mediaLabel}s, even if minor metadata corrections are needed.
Return every candidate — do not drop any entries from the output.`,
    input: `Validate these ${mediaLabel} candidates:\n${list}`,
  }));

  return (response.output_parsed as ValidatorOutput) ?? { candidates: [] };
}

export async function runValidator(
  candidates: RetrievalCandidate[],
  mediaType: MediaType = 'tv_show',
): Promise<ValidatorOutput> {
  const mediaLabel = mediaType === 'movie' ? 'movie' : 'TV show';
  const chunks = splitIntoChunks(candidates, CHUNK_SIZE);

  const chunkResults = await Promise.all(
    chunks.map((chunk) => runValidatorChunk(chunk, mediaLabel))
  );

  return {
    candidates: chunkResults.flatMap((r) => r.candidates),
  };
}
