// Category service handles admin operations on categories. The slug
// generation, uniqueness check, and append-on-end behaviour live here
// so the route handler is just a controller.

import { categoryRepository } from '@/lib/repositories/category.repository';
import { slugify } from '@/lib/utils/slug';
import { HttpError } from '@/lib/auth/session';
import { CreateCategoryInput, UpdateCategoryInput } from '@/lib/validators';

export const categoryService = {
  listActive() {
    return categoryRepository.listActive();
  },

  listAll() {
    return categoryRepository.listAll();
  },

  async getBySlug(slug: string) {
    const cat = await categoryRepository.findBySlug(slug);
    if (!cat) throw new HttpError(404, 'Category not found');
    return cat;
  },

  async create(input: CreateCategoryInput) {
    const slug = slugify(input.name);

    // Reject duplicate slugs early instead of relying on the DB error,
    // so the user sees a clean 409 with a helpful message.
    const existing = await categoryRepository.findBySlug(slug);
    if (existing) {
      throw new HttpError(409, 'A category with this name already exists');
    }

    const { _max } = await categoryRepository.maxSortOrder();
    const sortOrder = (_max.sortOrder ?? -1) + 1;

    return categoryRepository.create({ name: input.name, slug, sortOrder });
  },

  async update(id: number, input: UpdateCategoryInput) {
    const existing = await categoryRepository.findById(id);
    if (!existing) throw new HttpError(404, 'Category not found');

    // Renaming regenerates the slug, but we re-check uniqueness so two
    // categories never collide on slug.
    let slug: string | undefined;
    if (input.name && input.name !== existing.name) {
      const next = slugify(input.name);
      const clash = await categoryRepository.findBySlug(next);
      if (clash && clash.id !== id) {
        throw new HttpError(409, 'A category with this name already exists');
      }
      slug = next;
    }

    return categoryRepository.update(id, {
      ...(input.name !== undefined ? { name: input.name } : {}),
      ...(slug !== undefined ? { slug } : {}),
      ...(input.isActive !== undefined ? { isActive: input.isActive } : {}),
      ...(input.sortOrder !== undefined ? { sortOrder: input.sortOrder } : {}),
    });
  },

  // Soft delete: per the planning doc, we deactivate instead of hard
  // delete so existing questions stay searchable.
  async deactivate(id: number) {
    const existing = await categoryRepository.findById(id);
    if (!existing) throw new HttpError(404, 'Category not found');
    return categoryRepository.update(id, { isActive: false });
  },
};
