const SUGGESTION_COUNT = 3;

function normalizeSuggestions(items: unknown[]): string[] {
  return items
    .map(s => String(s).trim())
    .filter(Boolean)
    .slice(0, SUGGESTION_COUNT);
}

/** Parse LLM output — JSON array/object first, then numbered/bullet lists, then plain text. */
export function parseSuggestionsFromLlm(raw: string): string[] {
  const text = raw.trim();
  if (!text) throw new Error('AI returned empty content');

  const tryParse = (candidate: string): string[] | null => {
    try {
      const parsed = JSON.parse(candidate) as unknown;
      if (Array.isArray(parsed)) return normalizeSuggestions(parsed);
      if (parsed && typeof parsed === 'object') {
        const obj = parsed as Record<string, unknown>;
        for (const key of ['suggestions', 'replies', 'drafts', 'responses']) {
          if (Array.isArray(obj[key])) return normalizeSuggestions(obj[key] as unknown[]);
        }
      }
    } catch {
      /* try next strategy */
    }
    const arrayMatch = /\[[\s\S]*\]/.exec(candidate);
    if (arrayMatch) {
      try {
        const parsed = JSON.parse(arrayMatch[0]) as unknown;
        if (Array.isArray(parsed)) return normalizeSuggestions(parsed);
      } catch {
        /* continue */
      }
    }
    return null;
  };

  const fence = /```(?:json)?\s*([\s\S]*?)```/i.exec(text);
  for (const candidate of [text, fence?.[1]?.trim()]) {
    if (!candidate) continue;
    const parsed = tryParse(candidate);
    if (parsed?.length) return parsed;
  }

  const numbered = [...text.matchAll(/^\s*\d+[.)]\s+(.+)$/gm)].map(m => m[1].trim()).filter(Boolean);
  if (numbered.length) return numbered.slice(0, SUGGESTION_COUNT);

  const bullets = [...text.matchAll(/^\s*[-•*]\s+(.+)$/gm)].map(m => m[1].trim()).filter(Boolean);
  if (bullets.length >= 2) return bullets.slice(0, SUGGESTION_COUNT);

  if (text.length <= 2000) return [text];

  throw new Error('Could not parse suggestions from AI response');
}
