// packages/ai/src/index.ts
// Ollama AI utilities for TheKetoBay

const OLLAMA_URL = process.env.OLLAMA_URL || 'http://localhost:11434';

export interface OllamaOptions {
  model?: string;
  temperature?: number;
  maxTokens?: number;
  stream?: boolean;
}

export interface OllamaResponse {
  response: string;
  model: string;
  done: boolean;
  total_duration?: number;
}

/**
 * Send a prompt to Ollama and get a response
 */
export async function generate(prompt: string, options: OllamaOptions = {}): Promise<string> {
  const {
    model = process.env.OLLAMA_MODEL || 'llama3:8b',
    temperature = 0.7,
    maxTokens = 4000,
    stream = false
  } = options;

  const response = await fetch(`${OLLAMA_URL}/api/generate`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      model,
      prompt,
      stream,
      options: {
        temperature,
        num_predict: maxTokens,
      }
    })
  });

  if (!response.ok) {
    throw new Error(`Ollama error: ${response.status} ${response.statusText}`);
  }

  const data = await response.json() as OllamaResponse;
  return data.response;
}

/**
 * Check Ollama availability and list models
 */
export async function getStatus(): Promise<{ available: boolean; models: string[] }> {
  try {
    const res = await fetch(`${OLLAMA_URL}/api/tags`);
    const data = await res.json() as any;
    return {
      available: true,
      models: data.models?.map((m: any) => m.name) || []
    };
  } catch {
    return { available: false, models: [] };
  }
}

/**
 * Extract JSON from AI response (handles markdown code blocks)
 */
export function extractJson(text: string): any {
  // Try direct parse first
  try { return JSON.parse(text); } catch {}

  // Extract JSON from markdown code block
  const codeBlockMatch = text.match(/```(?:json)?\s*([\s\S]*?)```/);
  if (codeBlockMatch) {
    try { return JSON.parse(codeBlockMatch[1].trim()); } catch {}
  }

  // Extract first JSON object/array
  const jsonMatch = text.match(/(\{[\s\S]*\}|\[[\s\S]*\])/);
  if (jsonMatch) {
    try { return JSON.parse(jsonMatch[1]); } catch {}
  }

  throw new Error('Could not extract valid JSON from AI response');
}

/**
 * Keto-specific prompts
 */
export const prompts = {
  mealPlan: (params: {
    weightKg: number;
    targetWeightKg: number;
    heightCm: number;
    age: number;
    gender: string;
    activityLevel: string;
    goal: string;
    durationDays: number;
    budget: string;
    allergies: string[];
    dailyCalories: number;
    proteinG: number;
    fatG: number;
    netCarbsG: number;
  }) => `You are a professional ketogenic diet nutritionist. Generate a detailed ${params.durationDays}-day personalized keto meal plan.

USER PROFILE:
- Current weight: ${params.weightKg}kg | Target: ${params.targetWeightKg}kg
- Height: ${params.heightCm}cm | Age: ${params.age} | Gender: ${params.gender}
- Activity: ${params.activityLevel} | Goal: ${params.goal.replace(/_/g, ' ')}
- Budget: ${params.budget}
${params.allergies.length > 0 ? `- AVOID (allergies): ${params.allergies.join(', ')}` : ''}

DAILY MACRO TARGETS (STRICT):
- Calories: ${params.dailyCalories} kcal
- Protein: ${params.proteinG}g
- Fat: ${params.fatG}g
- Net Carbs: ${params.netCarbsG}g MAX (this is non-negotiable for ketosis)

REQUIREMENTS:
- 4 meals per day: breakfast, lunch, dinner, snack
- Use real, accessible foods
- Vary meals across days (no repeated breakfast 3 days in a row)
- Budget-appropriate ingredients for ${params.budget} budget
- Each meal must have accurate macro counts

Return ONLY valid JSON (no markdown, no explanation):
{
  "summary": "2-3 sentence personalized intro mentioning their specific goal and weight target",
  "dailyMacros": { "calories": ${params.dailyCalories}, "proteinG": ${params.proteinG}, "fatG": ${params.fatG}, "netCarbsG": ${params.netCarbsG} },
  "days": [
    {
      "day": 1,
      "totalCalories": 0,
      "totalNetCarbs": 0,
      "meals": {
        "breakfast": { "name": "", "description": "", "prepTime": "10 min", "calories": 0, "proteinG": 0, "fatG": 0, "netCarbsG": 0 },
        "lunch": { "name": "", "description": "", "prepTime": "15 min", "calories": 0, "proteinG": 0, "fatG": 0, "netCarbsG": 0 },
        "dinner": { "name": "", "description": "", "prepTime": "20 min", "calories": 0, "proteinG": 0, "fatG": 0, "netCarbsG": 0 },
        "snack": { "name": "", "description": "", "prepTime": "5 min", "calories": 0, "proteinG": 0, "fatG": 0, "netCarbsG": 0 }
      }
    }
  ],
  "shoppingList": {
    "proteins": ["item (amount for ${params.durationDays} days)"],
    "fats": ["item (amount)"],
    "vegetables": ["item (amount)"],
    "dairy": ["item (amount)"],
    "pantry": ["item (amount)"]
  },
  "tips": [
    "Personalized tip 1 based on their goal",
    "Personalized tip 2 based on their activity level",
    "Electrolyte tip specific to keto"
  ],
  "weeklyPrepTips": "2-3 sentences on batch cooking for the week"
}`,

  blogOutline: (topic: string) => `You are a keto diet expert content writer. Create a detailed SEO-optimized blog post outline for: "${topic}"

Return JSON only:
{
  "title": "SEO-optimized title (under 60 chars)",
  "metaDescription": "Meta description under 155 chars",
  "slug": "url-friendly-slug",
  "sections": [
    { "heading": "H2 heading", "points": ["key point 1", "key point 2"] }
  ],
  "keywords": ["primary keyword", "secondary keywords"],
  "estimatedReadTime": 8
}`
};
