import { base } from './base';
import axios from 'axios';

export interface Recipe {
  id: string;
  title?: string;
  instructions: string[];
  ingredients?: string;
  generatedRecipe?: string;
  createdAt?: string;
  audioUrl?: string;
}

export interface RecipeResponse {
  recipe: Recipe;
}

export interface RecipesResponse {
  recipes: Recipe[];
}

// Créer une nouvelle recette à partir d'un fichier audio
export const createRecipe = async (audioFile: File): Promise<Recipe> => {
  try {
    const formData = new FormData();
    formData.append('file', audioFile);

    const response = await base.post<RecipeResponse>('/recipes/create', formData, {
      headers: {
        'Content-Type': 'multipart/form-data'
      }
    });

    return response.data.recipe;
  } catch (error) {
    if (axios.isAxiosError(error) && error.response) {
      throw new Error(error.response.data.error || 'Erreur lors de la création de la recette');
    }
    throw new Error('Erreur réseau lors de la création de la recette');
  }
};

// Récupérer la liste des recettes de l'utilisateur
export const getRecipes = async (): Promise<Recipe[]> => {
  try {
    const response = await base.get<RecipesResponse>('/recipes/list');
    return response.data.recipes;
  } catch (error) {
    if (axios.isAxiosError(error) && error.response) {
      throw new Error(error.response.data.error || 'Erreur lors de la récupération des recettes');
    }
    throw new Error('Erreur réseau lors de la récupération des recettes');
  }
};

// Récupérer les détails d'une recette spécifique
export const getRecipeById = async (id: string): Promise<Recipe> => {
  try {
    const response = await base.get<RecipeResponse>(`/recipes/${id}`);
    return response.data.recipe;
  } catch (error) {
    if (axios.isAxiosError(error) && error.response) {
      throw new Error(error.response.data.error || 'Erreur lors de la récupération de la recette');
    }
    throw new Error('Erreur réseau lors de la récupération de la recette');
  }
};

// Supprimer une recette
export const deleteRecipe = async (id: string): Promise<boolean> => {
  try {
    await base.delete(`/recipes/${id}`);
    return true;
  } catch (error) {
    if (axios.isAxiosError(error) && error.response) {
      throw new Error(error.response.data.error || 'Erreur lors de la suppression de la recette');
    }
    throw new Error('Erreur réseau lors de la suppression de la recette');
  }
};

// -----------------------------------------------------------------------------
// Streaming (SSE via fetch + ReadableStream)
// -----------------------------------------------------------------------------

export type StreamEvent =
  | { type: 'progress'; step: string }
  | { type: 'transcription'; text: string }
  | { type: 'title'; title: string }
  | { type: 'description'; description: string }
  | { type: 'delta'; content: string }
  | { type: 'recipe'; recipe: StructuredRecipe }
  | { type: 'image'; url: string | null }
  | { type: 'saved'; id: string }
  | { type: 'error'; message: string }
  | { type: 'done' };

export interface StructuredRecipe {
  titre: string;
  description: string;
  origine_inspiration: string;
  ingredients: Array<{
    nom: string;
    quantite: string;
    notes: string | null;
    complement: boolean;
  }>;
  etapes: Array<{
    numero: number;
    instruction: string;
    duree_minutes: number | null;
  }>;
  temps_preparation: number;
  temps_cuisson: number;
  portions: number;
  difficulte: 'facile' | 'moyen' | 'difficile';
  conseils: string[];
  accord_boisson: string | null;
}

const API_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000';

/**
 * Lance une création de recette en streaming SSE.
 * Retourne un AsyncIterable d'événements que le composant peut consommer
 * avec `for await`.
 */
export async function* createRecipeStream(
  audioFile: File
): AsyncGenerator<StreamEvent, void, void> {
  const token = localStorage.getItem('token');
  const formData = new FormData();
  formData.append('file', audioFile);

  const response = await fetch(`${API_URL}/recipes/create-stream`, {
    method: 'POST',
    headers: token ? { Authorization: `Bearer ${token}` } : {},
    body: formData,
  });

  if (!response.ok) {
    const errText = await response.text();
    throw new Error(`HTTP ${response.status}: ${errText}`);
  }

  if (!response.body) {
    throw new Error('Pas de body dans la réponse');
  }

  const reader = response.body.getReader();
  const decoder = new TextDecoder();
  let buffer = '';

  try {
    while (true) {
      const { done, value } = await reader.read();
      if (done) break;

      buffer += decoder.decode(value, { stream: true });

      // Les événements SSE sont séparés par une ligne vide (\n\n)
      let sepIndex: number;
      while ((sepIndex = buffer.indexOf('\n\n')) !== -1) {
        const rawEvent = buffer.slice(0, sepIndex);
        buffer = buffer.slice(sepIndex + 2);

        // Parse les lignes event: et data:
        let eventName = 'message';
        let dataLine = '';
        for (const line of rawEvent.split('\n')) {
          if (line.startsWith('event: ')) eventName = line.slice(7).trim();
          else if (line.startsWith('data: ')) dataLine += line.slice(6);
          // Ignore les heartbeats (lignes commençant par ':')
        }

        if (!dataLine) continue;

        try {
          const data = JSON.parse(dataLine);
          yield { type: eventName, ...data } as StreamEvent;
        } catch (err) {
          console.warn('Event SSE non parsable:', rawEvent, err);
        }
      }
    }
  } finally {
    reader.releaseLock();
  }
}

// -----------------------------------------------------------------------------

export const recipeService = {
  createRecipe,
  createRecipeStream,
  getRecipes,
  getRecipeById,
  deleteRecipe,
};