/**
 * Snippet Capture Strategy Orchestrator
 * ----------------------------------------
 * Runs reformulations across all ingested opportunities in parallel batches.
 * Uses Promise.allSettled (never Promise.all). Hard 90s total timeout.
 *
 * Internal module.
 */

import { ingestSnippetOpportunities } from "./opportunity-ingestion";
import { generateReformulation } from "./reformulation-generator";
import type { SnippetCaptureStrategy, CapturedSnippetReformulation, SnippetType } from "./types";
import type { AiSnippetEligibility } from "../audit/types";

const SECTION_TIMEOUT_MS = 90_000;
const BATCH_SIZE = 5;

interface OrchestratorInput {
  existingAuditContext: {
    aiSnippetEligibility?: AiSnippetEligibility | null;
    serpAnalysis?: unknown;
  };
  brandContext: {
    brandName: string;
    vertical: string;
    brandDomain: string;
    brandSitemap?: string;
  };
}

function buildEmptyStrategy(opportunitiesIngested: number, runtimeSeconds: number): SnippetCaptureStrategy {
  return {
    hasStrategy: false,
    windowDate: new Date(),
    totalOpportunitiesAnalyzed: opportunitiesIngested,
    totalReformulationsGenerated: 0,
    totalEstimatedMonthlyTrafficGain: 0,
    totalEstimatedMonthlyRevenueGain: 0,
    reformulations: [],
    topPriorityReformulations: [],
    snippetTypeBreakdown: {},
    patentRelevance: "Prescriptive content reformulation derived from SERP feature analysis converts diagnostic snippet gaps into executable content specs with schema requirements.",
    costMetrics: {
      opportunitiesIngested,
      reformulationsGenerated: 0,
      reformulationsFailed: 0,
      estimatedCostUsd: 0,
      runtimeSeconds,
    },
  };
}

async function runBatch(
  opportunities: Parameters<typeof generateReformulation>[0][],
  brandContext: Parameters<typeof generateReformulation>[1],
): Promise<Array<CapturedSnippetReformulation | null>> {
  const settled = await Promise.allSettled(
    opportunities.map((opp) => generateReformulation(opp, brandContext)),
  );
  return settled.map((s) => (s.status === "fulfilled" ? s.value : null));
}

export async function generateSnippetCaptureStrategy(
  input: OrchestratorInput,
): Promise<SnippetCaptureStrategy | null> {
  const start = Date.now();

  const opportunities = ingestSnippetOpportunities(input.existingAuditContext);
  if (opportunities.length === 0) {
    return buildEmptyStrategy(0, (Date.now() - start) / 1000);
  }

  const reformulations: CapturedSnippetReformulation[] = [];
  let reformulationsFailed = 0;

  const runAllBatches = async (): Promise<void> => {
    for (let i = 0; i < opportunities.length; i += BATCH_SIZE) {
      const batch = opportunities.slice(i, i + BATCH_SIZE);
      const results = await runBatch(batch, input.brandContext);
      for (const result of results) {
        if (result) {
          reformulations.push(result);
        } else {
          reformulationsFailed++;
        }
      }
    }
  };

  const timeoutPromise = new Promise<"timeout">((resolve) =>
    setTimeout(() => resolve("timeout"), SECTION_TIMEOUT_MS),
  );

  await Promise.race([runAllBatches(), timeoutPromise]);

  const runtimeSeconds = (Date.now() - start) / 1000;

  if (reformulations.length === 0 && reformulationsFailed === 0) {
    return buildEmptyStrategy(opportunities.length, runtimeSeconds);
  }

  const totalTrafficGain = reformulations.reduce((sum, r) => sum + r.estimatedMonthlyTrafficGain, 0);
  const totalRevenueGain = reformulations.reduce((sum, r) => sum + r.estimatedMonthlyRevenueGain, 0);

  const topPriorityReformulations = [...reformulations]
    .sort((a, b) => b.estimatedMonthlyRevenueGain - a.estimatedMonthlyRevenueGain)
    .slice(0, 5);

  const snippetTypeBreakdown: Partial<Record<SnippetType, number>> = {};
  for (const r of reformulations) {
    snippetTypeBreakdown[r.snippetType] = (snippetTypeBreakdown[r.snippetType] ?? 0) + 1;
  }

  const estimatedCostUsd = Math.round(reformulations.length * 0.002 * 1000) / 1000;

  return {
    hasStrategy: reformulations.length > 0,
    windowDate: new Date(),
    totalOpportunitiesAnalyzed: opportunities.length,
    totalReformulationsGenerated: reformulations.length,
    totalEstimatedMonthlyTrafficGain: totalTrafficGain,
    totalEstimatedMonthlyRevenueGain: totalRevenueGain,
    reformulations,
    topPriorityReformulations,
    snippetTypeBreakdown,
    patentRelevance: "Prescriptive content reformulation derived from SERP feature analysis converts diagnostic snippet gaps into executable content specs with schema requirements.",
    costMetrics: {
      opportunitiesIngested: opportunities.length,
      reformulationsGenerated: reformulations.length,
      reformulationsFailed,
      estimatedCostUsd,
      runtimeSeconds,
    },
  };
}
