import { openai } from '../agent.js';
import type { InterpreterOutput, RetrievalOutput, RankingOutput, MediaType } from '../types/agents.js';
import { z } from 'zod';
import { zodTextFormat } from 'openai/helpers/zod';

const RankingSchema = z.object({
  definitely_like: z.array(z.string()),
  might_like: z.array(z.string()),
  questionable: z.array(z.string()),
  will_not_like: z.array(z.string())
});

export async function runRanking(
  interpreter: InterpreterOutput,
  retrieval: RetrievalOutput,
  mediaType: MediaType = 'tv_show',
): Promise<RankingOutput> {
  const mediaLabel = mediaType === 'movie' ? 'movie' : 'TV show';

  // Phase 1: Pre-filter — remove avoidance violations
  const avoidList = interpreter.avoid.map((a) => a.toLowerCase());
  const filtered = retrieval.candidates.filter((c) => {
    const text = (c.title + ' ' + c.reason).toLowerCase();
    return !avoidList.some((a) => text.includes(a));
  });

  // Phase 2: Chunked ranking — split into groups of ~15
  const CHUNK_SIZE = 15;
  const chunks: typeof filtered[] = [];
  for (let i = 0; i < filtered.length; i += CHUNK_SIZE) {
    chunks.push(filtered.slice(i, i + CHUNK_SIZE));
  }

  const allBuckets: RankingOutput = {
    definitely_like: [],
    might_like: [],
    questionable: [],
    will_not_like: [],
  };

  for (const chunk of chunks) {
    const chunkTitles = chunk.map((c) => `- ${c.title}: ${c.reason}`).join('\n');

    const response = await openai.responses.parse({
      model: 'gpt-5.4',
      temperature: 0.2,
      service_tier: 'flex',
      text: { format: zodTextFormat(RankingSchema, "ranking") },
      instructions: `You are a ${mediaLabel} ranking critic. Assign each ${mediaLabel} to exactly one of four confidence buckets based on how well it matches the user's preferences.

Buckets:
- "definitely_like": Near-perfect match to all preferences
- "might_like": Strong match to most preferences
- "questionable": Partial alignment, some aspects don't match
- "will_not_like": Likely mismatch, conflicts with preferences or avoidance criteria

Every ${mediaLabel} in the input must appear in exactly one bucket. Use the title exactly as given.`,
      input: `User preferences:
Liked ${mediaLabel}s: ${JSON.stringify(interpreter.liked)}
Themes: ${JSON.stringify(interpreter.themes)}
Character preferences: ${JSON.stringify(interpreter.character_preferences)}
Tone: ${JSON.stringify(interpreter.tone)}
Avoid: ${JSON.stringify(interpreter.avoid)}

Rank these ${mediaLabel}s:
${chunkTitles}`,
    });

    const chunkResult = (response.output_parsed as Partial<RankingOutput>) ?? {};

    allBuckets.definitely_like.push(...(chunkResult.definitely_like ?? []));
    allBuckets.might_like.push(...(chunkResult.might_like ?? []));
    allBuckets.questionable.push(...(chunkResult.questionable ?? []));
    allBuckets.will_not_like.push(...(chunkResult.will_not_like ?? []));
  }

  return allBuckets;
}
