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<string> {
  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<Result<Sport[]>> {
  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,
  });
}
