import { Router, Request, Response } from 'express';
import { asyncHandler } from '../utils/asyncHandler';
import { db } from '../db';
import { categories } from '../db/schema';
import { eq, and, desc, asc } from 'drizzle-orm';
import { authMiddleware } from '../utils/auth';
import { AppError } from '../middleware/errorHandler';
import { categoryCreateSchema, categoryUpdateSchema } from '../utils/validation';

const router = Router();

router.use(authMiddleware);

router.get('/', asyncHandler(async (req: Request, res: Response) => {
  const userCategories = await db
    .select()
    .from(categories)
    .where(eq(categories.userId, req.user!.userId))
    .orderBy(asc(categories.order), asc(categories.createdAt));

  res.json({ categories: userCategories });
}));

router.post('/', asyncHandler(async (req: Request, res: Response) => {
  const data = categoryCreateSchema.parse(req.body);
  const userId = req.user!.userId;
  const now = Date.now();

  const maxOrder = await db
    .select({ order: categories.order })
    .from(categories)
    .where(eq(categories.userId, userId))
    .orderBy(desc(categories.order))
    .limit(1);

  const newCategory = {
    id: `cat_${Date.now().toString(36)}${Math.random().toString(36).slice(2, 6)}`,
    userId,
    name: data.name,
    color: data.color,
    order: data.order ?? (maxOrder[0]?.order ?? -1) + 1,
    createdAt: now,
    updatedAt: now,
  };

  await db.insert(categories).values(newCategory);

  res.status(201).json(newCategory);
}));

router.patch('/:id', asyncHandler(async (req: Request, res: Response) => {
  const data = categoryUpdateSchema.parse(req.body);
  const userId = req.user!.userId;

  const existing = await db
    .select()
    .from(categories)
    .where(and(eq(categories.id, req.params.id), eq(categories.userId, userId)))
    .limit(1);

  if (existing.length === 0) {
    throw new AppError('NOT_FOUND', 'Category not found', 404);
  }

  const now = Date.now();
  const updated = await db
    .update(categories)
    .set({ ...data, updatedAt: now })
    .where(and(eq(categories.id, req.params.id), eq(categories.userId, userId)))
    .returning();

  res.json(updated[0]);
}));

router.delete('/:id', asyncHandler(async (req: Request, res: Response) => {
  const userId = req.user!.userId;

  const existing = await db
    .select()
    .from(categories)
    .where(and(eq(categories.id, req.params.id), eq(categories.userId, userId)))
    .limit(1);

  if (existing.length === 0) {
    throw new AppError('NOT_FOUND', 'Category not found', 404);
  }

  await db
    .delete(categories)
    .where(and(eq(categories.id, req.params.id), eq(categories.userId, userId)));

  res.status(204).send();
}));

export default router;