import { Prisma, Sport } from '@/generated/prisma/client'; import { Errors } from '@/lib/errors'; import { db } from '@/lib/prisma'; import { Result, err, ok } from '@/lib/result'; import { v7 as uuidv7 } from 'uuid'; export type CreateSportInput = { name: string; }; export type UpdateSportInput = { name?: string; isActive?: boolean; }; function slugify(value: string): string { return value .normalize('NFD') .replace(/[\u0300-\u036f]/g, '') .toLowerCase() .trim() .replace(/[^a-z0-9\s-]/g, '') .replace(/\s+/g, '-') .replace(/-+/g, '-'); } async function buildUniqueSlug(source: string, excludeSportId?: string): Promise { const base = slugify(source); const fallback = base.length > 0 ? base : `sport-${uuidv7().slice(0, 8)}`; let candidate = fallback; let index = 1; while (true) { const existing = await db.sport.findFirst({ where: { slug: candidate, ...(excludeSportId ? { id: { not: excludeSportId, }, } : {}), }, select: { id: true }, }); if (!existing) return candidate; index += 1; candidate = `${fallback}-${index}`; } } export async function listSports(): Promise> { const sports = await db.sport.findMany({ orderBy: { name: 'asc' }, }); return ok(sports); } export async function createSport(input: CreateSportInput) { const slug = await buildUniqueSlug(input.name); const existing = await db.sport.count({ where: { slug }, }); if (existing > 0) { return err(Errors.conflict('Ya existe un deporte con ese nombre.')); } const created = await db.sport.create({ data: { id: uuidv7(), name: input.name.trim(), slug, isActive: true, }, }); return ok(created); } export async function getSportById(id: string) { return db.sport.findUnique({ where: { id } }); } export async function updateSport(id: string, input: UpdateSportInput) { const data: Prisma.SportUncheckedUpdateInput = {}; if (input.name) { data.name = input.name; data.slug = await buildUniqueSlug(input.name, id); } if (input.isActive !== undefined) { data.isActive = input.isActive; } return db.sport.update({ where: { id }, data, }); }