// src/routes/recipe.routes.ts
import { Router } from 'express';
import { z } from 'zod';
import * as db from '../services/db/index.db';
import { validateRequest } from '../middleware/validation.middleware';
import { requiredString, numericIdParam, optionalNumeric } from '../utils/zodUtils';

const router = Router();

const bySalePercentageSchema = z.object({
  query: z.object({
    minPercentage: optionalNumeric({ default: 50, min: 0, max: 100 }),
  }),
});

const bySaleIngredientsSchema = z.object({
  query: z.object({
    minIngredients: optionalNumeric({ default: 3, integer: true, positive: true }),
  }),
});

const byIngredientAndTagSchema = z.object({
  query: z.object({
    ingredient: requiredString('Query parameter "ingredient" is required.'),
    tag: requiredString('Query parameter "tag" is required.'),
  }),
});

const recipeIdParamsSchema = numericIdParam('recipeId');

/**
 * GET /api/recipes/by-sale-percentage - Get recipes based on the percentage of their ingredients on sale.
 */
router.get(
  '/by-sale-percentage',
  validateRequest(bySalePercentageSchema),
  async (req, res, next) => {
    try {
      // Explicitly parse req.query to apply coercion (string -> number) and default values
      const { query } = bySalePercentageSchema.parse({ query: req.query });
      const recipes = await db.recipeRepo.getRecipesBySalePercentage(query.minPercentage!, req.log);
      res.json(recipes);
    } catch (error) {
      req.log.error({ error }, 'Error fetching recipes in /api/recipes/by-sale-percentage:');
      next(error);
    }
  },
);

/**
 * GET /api/recipes/by-sale-ingredients - Get recipes by the minimum number of sale ingredients.
 */
router.get(
  '/by-sale-ingredients',
  validateRequest(bySaleIngredientsSchema),
  async (req, res, next) => {
    try {
      // Explicitly parse req.query to apply coercion (string -> number) and default values
      const { query } = bySaleIngredientsSchema.parse({ query: req.query });
      const recipes = await db.recipeRepo.getRecipesByMinSaleIngredients(
        query.minIngredients!,
        req.log,
      );
      res.json(recipes);
    } catch (error) {
      req.log.error({ error }, 'Error fetching recipes in /api/recipes/by-sale-ingredients:');
      next(error);
    }
  },
);

/**
 * GET /api/recipes/by-ingredient-and-tag - Find recipes by a specific ingredient and tag.
 */
router.get(
  '/by-ingredient-and-tag',
  validateRequest(byIngredientAndTagSchema),
  async (req, res, next) => {
    try {
      const { query } = byIngredientAndTagSchema.parse({ query: req.query });
      const recipes = await db.recipeRepo.findRecipesByIngredientAndTag(
        query.ingredient,
        query.tag,
        req.log,
      );
      res.json(recipes);
    } catch (error) {
      req.log.error({ error }, 'Error fetching recipes in /api/recipes/by-ingredient-and-tag:');
      next(error);
    }
  },
);

/**
 * GET /api/recipes/:recipeId/comments - Get all comments for a specific recipe.
 */
router.get('/:recipeId/comments', validateRequest(recipeIdParamsSchema), async (req, res, next) => {
  try {
    // Explicitly parse req.params to coerce recipeId to a number
    const { params } = recipeIdParamsSchema.parse({ params: req.params });
    const comments = await db.recipeRepo.getRecipeComments(params.recipeId, req.log);
    res.json(comments);
  } catch (error) {
    req.log.error({ error }, `Error fetching comments for recipe ID ${req.params.recipeId}:`);
    next(error);
  }
});

/**
 * GET /api/recipes/:recipeId - Get a single recipe by its ID, including ingredients and tags.
 */
router.get('/:recipeId', validateRequest(recipeIdParamsSchema), async (req, res, next) => {
  try {
    // Explicitly parse req.params to coerce recipeId to a number
    const { params } = recipeIdParamsSchema.parse({ params: req.params });
    const recipe = await db.recipeRepo.getRecipeById(params.recipeId, req.log);
    res.json(recipe);
  } catch (error) {
    req.log.error({ error }, `Error fetching recipe ID ${req.params.recipeId}:`);
    next(error);
  }
});

export default router;
