import * as fs from 'node:fs';
import type { FastifyInstance, FastifyPluginAsync } from 'fastify';
import multipart from '@fastify/multipart';
import { deleteFile } from '../utils/storage';

const FREE_PLAN_LIMIT = 5;

const recipesRoutes: FastifyPluginAsync = async (fastify: FastifyInstance) => {
  await fastify.register(multipart, {
    limits: {
      fileSize: 15 * 1024 * 1024, // 15 MB
      files: 1,
    },
  });

  fastify.addHook('preHandler', fastify.authenticate);

  // --- POST /create ---
  fastify.post('/create', async (request, reply) => {
    try {
      const data = await request.file();
      if (!data) {
        return reply.code(400).send({ error: 'Fichier audio requis' });
      }

      const [user, recipeCount] = await Promise.all([
        fastify.prisma.user.findUnique({ where: { id: request.user.id } }),
        fastify.prisma.recipe.count({ where: { userId: request.user.id } }),
      ]);

      if (!user) {
        return reply.code(404).send({ error: 'Utilisateur non trouvé' });
      }

      const isFree = !user.subscription || user.subscription === 'free';
      if (isFree && recipeCount >= FREE_PLAN_LIMIT) {
        return reply.code(403).send({
          error: `Limite de ${FREE_PLAN_LIMIT} recettes atteinte pour le plan gratuit. Passez au plan premium pour en créer davantage.`,
        });
      }

      const audioResult = await fastify.saveAudioFile(data);
      const audioUrl = audioResult.url || audioResult.localPath || null;
      const audioStoragePath = audioResult.path ?? null;

      const transcription = await fastify.transcribeAudio(audioResult);

      const recipeData = await fastify.generateRecipe(
        transcription,
        'Crée une recette délicieuse et détaillée'
      );

      const ingredientsString = Array.isArray(recipeData.ingredients)
        ? recipeData.ingredients.join('\n')
        : recipeData.ingredients || '';

      const stepsString = Array.isArray(recipeData.etapes)
        ? recipeData.etapes.join('\n')
        : recipeData.etapes || '';

      const recipe = await fastify.prisma.recipe.create({
        data: {
          title: recipeData.titre || 'Recette sans titre',
          ingredients: ingredientsString,
          userPrompt: transcription,
          // On stocke la version structurée riche (avec notes, accord boisson,
          // origine, etc.) plutôt que la forme aplatie.
          generatedRecipe: JSON.stringify(recipeData.structured ?? recipeData),
          imageUrl: recipeData.image_url ?? null,
          preparationTime: recipeData.temps_preparation ?? null,
          cookingTime: recipeData.temps_cuisson ?? null,
          servings: recipeData.portions ?? null,
          difficulty: recipeData.difficulte ?? null,
          steps: stepsString,
          tips: recipeData.conseils ?? null,
          audioUrl: audioStoragePath || audioUrl,
          userId: request.user.id,
        },
      });

      return {
        recipe: {
          id: recipe.id,
          title: recipe.title,
          ingredients: recipe.ingredients,
          preparationTime: recipe.preparationTime,
          cookingTime: recipe.cookingTime,
          servings: recipe.servings,
          difficulty: recipe.difficulty,
          steps: recipe.steps,
          tips: recipe.tips,
          imageUrl: recipe.imageUrl,
          audioUrl,
          createdAt: recipe.createdAt,
        },
      };
    } catch (error) {
      fastify.log.error(error);
      return reply.code(500).send({ error: 'Erreur lors de la création de la recette' });
    }
  });

  // --- GET /list ---
  fastify.get('/list', async (request, reply) => {
    try {
      const recipes = await fastify.prisma.recipe.findMany({
        where: { userId: request.user.id },
        orderBy: { createdAt: 'desc' },
        select: {
          id: true,
          title: true,
          ingredients: true,
          preparationTime: true,
          cookingTime: true,
          servings: true,
          difficulty: true,
          imageUrl: true,
          createdAt: true,
        },
      });

      return { recipes };
    } catch (error) {
      fastify.log.error(error);
      return reply.code(500).send({ error: 'Erreur lors de la récupération des recettes' });
    }
  });

  // --- GET /:id ---
  fastify.get<{ Params: { id: string } }>('/:id', async (request, reply) => {
    try {
      const recipe = await fastify.prisma.recipe.findFirst({
        where: {
          id: request.params.id,
          userId: request.user.id,
        },
      });

      if (!recipe) {
        return reply.code(404).send({ error: 'Recette non trouvée' });
      }

      let parsed: unknown = null;
      if (recipe.generatedRecipe) {
        try {
          parsed = JSON.parse(recipe.generatedRecipe);
        } catch (err) {
          fastify.log.warn(
            `generatedRecipe corrompu pour ${recipe.id}: ${(err as Error).message}`
          );
        }
      }

      return { recipe: { ...recipe, generatedRecipe: parsed } };
    } catch (error) {
      fastify.log.error(error);
      return reply.code(500).send({ error: 'Erreur lors de la récupération de la recette' });
    }
  });

  // --- DELETE /:id ---
  fastify.delete<{ Params: { id: string } }>('/:id', async (request, reply) => {
    try {
      const recipe = await fastify.prisma.recipe.findUnique({
        where: { id: request.params.id },
      });

      if (!recipe) {
        return reply.code(404).send({ error: 'Recette non trouvée' });
      }

      if (recipe.userId !== request.user.id) {
        return reply.code(403).send({ error: 'Non autorisé' });
      }

      await fastify.prisma.recipe.delete({ where: { id: request.params.id } });

      // Nettoyage best-effort du fichier audio
      if (recipe.audioUrl) {
        try {
          if (recipe.audioUrl.startsWith('http')) {
            // URL presignée — ne contient pas d'info de clé fiable, skip
          } else if (recipe.audioUrl.includes('/') && !recipe.audioUrl.startsWith('./')) {
            await deleteFile(recipe.audioUrl).catch(() => {});
          } else if (fs.existsSync(recipe.audioUrl)) {
            fs.unlinkSync(recipe.audioUrl);
          }
        } catch (cleanupErr) {
          fastify.log.warn(`Nettoyage audio échoué: ${(cleanupErr as Error).message}`);
        }
      }

      return { success: true };
    } catch (error) {
      fastify.log.error(error);
      return reply.code(500).send({ error: 'Erreur lors de la suppression de la recette' });
    }
  });
};

export default recipesRoutes;
