import { Router, Request, Response, NextFunction } from 'express';
import { PrismaClient } from '@prisma/client';
import Joi from 'joi';

const router = Router();
const prisma = new PrismaClient();

// Validation schemas
const recipeSchema = Joi.object({
  recipeNumber: Joi.string().optional().allow(''),
  title: Joi.string().required().min(1).max(255),
  description: Joi.string().optional().allow(''),
  category: Joi.string().optional().allow(''),
  preparation: Joi.string().optional().allow(''),
  servings: Joi.number().integer().min(1).default(1),
  ingredients: Joi.string().optional().allow(''),
  instructions: Joi.string().optional().allow(''),
  comment: Joi.string().optional().allow(''),
});

const updateRecipeSchema = recipeSchema;

// Get all recipes with search and pagination
router.get('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { 
      search = '', 
      category = '', 
      page = '1', 
      limit = '10',
      sortBy = 'title',
      sortOrder = 'asc'
    } = req.query;

    const pageNum = parseInt(page as string);
    const limitNum = parseInt(limit as string);
    const skip = (pageNum - 1) * limitNum;

    const where: any = {};
    
    if (search) {
      where.OR = [
        { title: { contains: search as string } },
        { description: { contains: search as string } },
        { ingredients: { contains: search as string } },
      ];
    }
    
    if (category) {
      where.category = { contains: category as string };
    }

    const [recipes, total] = await Promise.all([
      prisma.recipe.findMany({
        where,
        include: {
          images: true,
          ingredientsList: true,
        },
        orderBy: { [sortBy as string]: sortOrder as 'asc' | 'desc' },
        skip,
        take: limitNum,
      }),
      prisma.recipe.count({ where })
    ]);

    return res.json({
      success: true,
      data: recipes,
      pagination: {
        page: pageNum,
        limit: limitNum,
        total,
        pages: Math.ceil(total / limitNum),
      },
    });
  } catch (error) {
    next(error);
  }
});

// Get single recipe by ID
// Get recipe by ID
router.get('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { id } = req.params;
    
    if (!id) {
      return res.status(400).json({
        success: false,
        message: 'Recipe ID is required',
      });
    }

    const recipeId = parseInt(id);
    if (isNaN(recipeId)) {
      return res.status(400).json({
        success: false,
        message: 'Invalid recipe ID format',
      });
    }
    
    const recipe = await prisma.recipe.findUnique({
      where: { id: recipeId },
      include: {
        images: true,
        ingredientsList: true,
      }
    });

    if (!recipe) {
      return res.status(404).json({
        success: false,
        message: 'Recipe not found',
      });
    }

    // Try to load ingredients from separate ingredients table if not already loaded
    if ((!recipe.ingredients || recipe.ingredients.trim() === '' || recipe.ingredients.length < 10) && recipe.recipeNumber) {
      try {
        // Try with "R" prefix (e.g., "30" -> "R030")
        const paddedNumber = recipe.recipeNumber.padStart(3, '0');
        const recipeNumberWithR = `R${paddedNumber}`;
        
        const separateIngredients = await prisma.ingredient.findFirst({
          where: { recipeNumber: recipeNumberWithR }
        });
        
        if (separateIngredients && separateIngredients.ingredients) {
          // Update the recipe object with the found ingredients
          (recipe as any).ingredients = separateIngredients.ingredients;
        }
      } catch (ingredientError) {
        console.log(`Could not load separate ingredients for recipe ${recipe.recipeNumber}:`, ingredientError);
      }
    }

    return res.json({
      success: true,
      data: recipe,
    });
  } catch (error) {
    next(error);
  }
});

// Create new recipe
router.post('/', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { error, value } = recipeSchema.validate(req.body);
    
    if (error) {
      return res.status(400).json({
        success: false,
        message: 'Validation error',
        details: error.details,
      });
    }

    // Generate recipeNumber if not provided
    if (!value.recipeNumber || value.recipeNumber.trim() === '') {
      // Find the highest existing recipe number
      const lastRecipe = await prisma.recipe.findFirst({
        orderBy: { id: 'desc' },
        select: { recipeNumber: true }
      });
      
      let nextNumber = 1;
      if (lastRecipe?.recipeNumber) {
        // Extract number from recipeNumber like "R030" -> 30
        const match = lastRecipe.recipeNumber.match(/\d+/);
        if (match) {
          nextNumber = parseInt(match[0]) + 1;
        }
      }
      
      // Format as R### (e.g., R001, R032)
      value.recipeNumber = `R${nextNumber.toString().padStart(3, '0')}`;
    }

    const recipe = await prisma.recipe.create({
      data: value,
      include: {
        images: true,
        ingredientsList: true,
      }
    });

    return res.status(201).json({
      success: true,
      data: recipe,
      message: 'Recipe created successfully',
    });
  } catch (error) {
    next(error);
  }
});

// Update recipe
router.put('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { id } = req.params;
    
    if (!id) {
      return res.status(400).json({
        success: false,
        message: 'Recipe ID is required',
      });
    }
    
    const { error, value } = updateRecipeSchema.validate(req.body);
    
    if (error) {
      return res.status(400).json({
        success: false,
        message: 'Validation error',
        details: error.details,
      });
    }

    const recipe = await prisma.recipe.update({
      where: { id: parseInt(id) },
      data: value,
      include: {
        images: true,
        ingredientsList: true,
      }
    });

    return res.json({
      success: true,
      data: recipe,
      message: 'Recipe updated successfully',
    });
  } catch (error) {
    next(error);
  }
});

// Delete recipe
router.delete('/:id', async (req: Request, res: Response, next: NextFunction) => {
  try {
    const { id } = req.params;
    
    if (!id) {
      return res.status(400).json({
        success: false,
        message: 'Recipe ID is required',
      });
    }
    
    await prisma.recipe.delete({
      where: { id: parseInt(id) }
    });

    return res.json({
      success: true,
      message: 'Recipe deleted successfully',
    });
  } catch (error) {
    next(error);
  }
});

export default router;