import { Router } from 'express';
import { z } from 'zod';
import type { Database } from 'sql.js';
import { TagService } from '../services/TagService.js';
import { asyncHandler } from '../middleware.js';

const createTagSchema = z.object({
  name: z.string().min(1, 'Name is required'),
});

const updateTagSchema = z.object({
  name: z.string().min(1).optional(),
});

const assignTagSchema = z.object({
  tag_id: z.number().int().positive(),
});

export function createTagRoutes(db: Database): Router {
  const router = Router();
  const tagService = new TagService(db);

  router.get('/', asyncHandler(async (req, res) => {
    const tags = tagService.list();
    res.json({ success: true, data: tags, error: null });
  }));

  router.get('/:id', asyncHandler(async (req, res) => {
    const id = parseInt(req.params.id, 10);
    if (isNaN(id)) {
      res.status(400).json({ success: false, data: null, error: 'Invalid tag ID' });
      return;
    }
    const tag = tagService.get(id);
    if (!tag) {
      res.status(404).json({ success: false, data: null, error: 'Tag not found' });
      return;
    }
    res.json({ success: true, data: tag, error: null });
  }));

  router.post('/', asyncHandler(async (req, res) => {
    const data = createTagSchema.parse(req.body);
    const tag = tagService.create(data);
    res.status(201).json({ success: true, data: tag, error: null });
  }));

  router.put('/:id', asyncHandler(async (req, res) => {
    const id = parseInt(req.params.id, 10);
    if (isNaN(id)) {
      res.status(400).json({ success: false, data: null, error: 'Invalid tag ID' });
      return;
    }
    const data = updateTagSchema.parse(req.body);
    const tag = tagService.update(id, data);
    if (!tag) {
      res.status(404).json({ success: false, data: null, error: 'Tag not found' });
      return;
    }
    res.json({ success: true, data: tag, error: null });
  }));

  router.delete('/:id', asyncHandler(async (req, res) => {
    const id = parseInt(req.params.id, 10);
    if (isNaN(id)) {
      res.status(400).json({ success: false, data: null, error: 'Invalid tag ID' });
      return;
    }
    const deleted = tagService.delete(id);
    if (!deleted) {
      res.status(404).json({ success: false, data: null, error: 'Tag not found' });
      return;
    }
    res.json({ success: true, data: true, error: null });
  }));

  // Tag <-> Recipe assignment/removal
  router.post('/:id/assign', asyncHandler(async (req, res) => {
    const recipeId = parseInt(req.params.id, 10);
    if (isNaN(recipeId)) {
      res.status(400).json({ success: false, data: null, error: 'Invalid recipe ID' });
      return;
    }
    const data = assignTagSchema.parse(req.body);
    const ok = tagService.assignToRecipe(recipeId, data.tag_id);
    res.json({ success: ok, data: ok, error: ok ? null : 'Assignment failed' });
  }));

  router.post('/:id/remove', asyncHandler(async (req, res) => {
    const recipeId = parseInt(req.params.id, 10);
    if (isNaN(recipeId)) {
      res.status(400).json({ success: false, data: null, error: 'Invalid recipe ID' });
      return;
    }
    const data = assignTagSchema.parse(req.body);
    const ok = tagService.removeFromRecipe(recipeId, data.tag_id);
    res.json({ success: ok, data: ok, error: ok ? null : 'Remove failed' });
  }));

  return router;
}
