import { Router } from 'express';
import { z } from 'zod';
import type { Database } from 'sql.js';
import { TagService } from '../services/TagService.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('/', (req, res) => {
    try {
      const tags = tagService.list();
      res.json({ success: true, data: tags, error: null });
    } catch (error) {
      res.status(500).json({ success: false, data: null, error: 'Internal server error' });
    }
  });

  router.get('/:id', (req, res) => {
    try {
      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 });
    } catch (error) {
      res.status(500).json({ success: false, data: null, error: 'Internal server error' });
    }
  });

  router.post('/', (req, res) => {
    try {
      const data = createTagSchema.parse(req.body);
      const tag = tagService.create(data);
      res.status(201).json({ success: true, data: tag, error: null });
    } catch (error) {
      if (error instanceof z.ZodError) {
        res.status(400).json({ success: false, data: null, error: error.errors });
      } else if (error instanceof Error) {
        res.status(400).json({ success: false, data: null, error: error.message });
      } else {
        res.status(500).json({ success: false, data: null, error: 'Internal server error' });
      }
    }
  });

  router.put('/:id', (req, res) => {
    try {
      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 });
    } catch (error) {
      if (error instanceof z.ZodError) {
        res.status(400).json({ success: false, data: null, error: error.errors });
      } else if (error instanceof Error) {
        res.status(400).json({ success: false, data: null, error: error.message });
      } else {
        res.status(500).json({ success: false, data: null, error: 'Internal server error' });
      }
    }
  });

  router.delete('/:id', (req, res) => {
    try {
      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 });
    } catch (error) {
      res.status(500).json({ success: false, data: null, error: 'Internal server error' });
    }
  });

  // Tag <-> Recipe assignment/removal
  router.post('/:id/assign', (req, res) => {
    try {
      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' });
    } catch (error) {
      res.status(400).json({ success: false, data: null, error: 'Invalid request' });
    }
  });

  router.post('/:id/remove', (req, res) => {
    try {
      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' });
    } catch (error) {
      res.status(400).json({ success: false, data: null, error: 'Invalid request' });
    }
  });
  return router;
}
