const OPENAI_RESPONSES_URL = 'https://api.openai.com/v1/responses';

type SafetyIssue = {
  type: 'critical' | 'warning' | 'suggestion';
  category: string;
  message: string;
  source: string;
  sourceUrl: string;
};

type ProtocolAnalysis = {
  issues: SafetyIssue[];
};

const analysisSchema = {
  type: 'object',
  properties: {
    issues: {
      type: 'array',
      description: 'Safety issues found in the protocol. Return an empty array when no issues are found.',
      items: {
        type: 'object',
        properties: {
          type: {
            type: 'string',
            enum: ['critical', 'warning', 'suggestion'],
            description: 'critical for immediate safety risks, warning for notable compliance or procedural gaps, suggestion for lower-risk improvements.',
          },
          category: {
            type: 'string',
            description: 'Short label such as PPE Requirements, Ventilation, Waste Disposal, Emergency Procedures, or Chemical Storage.',
          },
          message: {
            type: 'string',
            description: 'Clear, actionable finding written for lab staff.',
          },
          source: {
            type: 'string',
            description: 'Short source title, regulation, or guidance name.',
          },
          sourceUrl: {
            type: 'string',
            description: 'Clickable URL for the source.',
          },
        },
        required: ['type', 'category', 'message', 'source', 'sourceUrl'],
        additionalProperties: false,
      },
    },
  },
  required: ['issues'],
  additionalProperties: false,
};

function getOutputText(response: any): string {
  if (typeof response.output_text === 'string') return response.output_text;

  const parts: string[] = [];
  for (const item of response.output ?? []) {
    for (const content of item.content ?? []) {
      if (content.type === 'output_text' && typeof content.text === 'string') {
        parts.push(content.text);
      }
    }
  }
  return parts.join('\n');
}

function normalizeAnalysis(value: unknown): SafetyIssue[] {
  const parsed = value as Partial<ProtocolAnalysis>;
  if (!Array.isArray(parsed.issues)) return [];

  return parsed.issues
    .filter((issue): issue is SafetyIssue =>
      issue != null &&
      ['critical', 'warning', 'suggestion'].includes((issue as SafetyIssue).type) &&
      typeof (issue as SafetyIssue).category === 'string' &&
      typeof (issue as SafetyIssue).message === 'string' &&
      typeof (issue as SafetyIssue).source === 'string' &&
      typeof (issue as SafetyIssue).sourceUrl === 'string'
    )
    .map(issue => ({
      type: issue.type,
      category: issue.category.trim(),
      message: issue.message.trim(),
      source: issue.source.trim(),
      sourceUrl: issue.sourceUrl.trim(),
    }))
    .filter(issue => issue.category && issue.message && issue.source && issue.sourceUrl);
}

export async function analyzeProtocolWithOpenAI(protocolText: string): Promise<SafetyIssue[]> {
  const apiKey = process.env.OPENAI_API_KEY;
  if (!apiKey) {
    throw new Error('OPENAI_API_KEY is not configured');
  }

  const model = process.env.OPENAI_MODEL || 'gpt-5-mini';
  const requestBody: Record<string, unknown> = {
    model,
    input: [
      {
        role: 'system',
        content:
          'You are a laboratory safety reviewer. Analyze protocols for practical safety and compliance gaps. ' +
          'Return JSON only. Each finding must use one of: critical, warning, suggestion. ' +
          'Cite authoritative sources such as OSHA, EPA, CDC/NIOSH, NFPA, ANSI, or university EHS guidance. ' +
          'Do not invent source URLs; use a relevant official source URL for every finding.',
      },
      {
        role: 'user',
        content:
          'Analyze this lab protocol. Focus on PPE, chemical compatibility, ventilation, waste disposal, emergency procedures, storage, and missing hazard controls.\n\n' +
          protocolText,
      },
    ],
    tools: [
      {
        type: 'web_search',
        filters: {
          allowed_domains: [
            'www.osha.gov',
            'www.epa.gov',
            'www.cdc.gov',
            'www.nfpa.org',
            'www.ansi.org',
            'ehs.princeton.edu',
            'ehs.stanford.edu',
            'ehs.ucsf.edu',
          ],
        },
      },
    ],
    tool_choice: 'required',
    text: {
      format: {
        type: 'json_schema',
        name: 'protocol_safety_analysis',
        strict: true,
        schema: analysisSchema,
      },
    },
  };

  if (model.startsWith('gpt-5')) {
    requestBody.reasoning = { effort: 'low' };
  }

  const response = await fetch(OPENAI_RESPONSES_URL, {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${apiKey}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(requestBody),
  });

  if (!response.ok) {
    const errorBody = await response.text().catch(() => '');
    throw new Error(`OpenAI protocol analysis failed (${response.status}): ${errorBody || response.statusText}`);
  }

  const data = await response.json();
  const outputText = getOutputText(data);
  if (!outputText) {
    throw new Error('OpenAI returned an empty protocol analysis');
  }

  let parsed: unknown;
  try {
    parsed = JSON.parse(outputText);
  } catch {
    throw new Error('OpenAI returned protocol analysis that was not valid JSON');
  }

  return normalizeAnalysis(parsed);
}
