import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { CreateDepartmentDto } from './dto/create-department.dto';
import { UpdateDepartmentDto } from './dto/update-department.dto';
import { FindDepartmentsDto } from './dto/find-departments.dto';
import { Prisma } from '@prisma/client';

export interface PaginatedResult<T> {
  data: T[];
  nextCursor: string | null;
  hasMore: boolean;
}

@Injectable()
export class DepartmentsService {
  constructor(private readonly prisma: PrismaService) {}

  async findAll(
    clubId: string,
    params: FindDepartmentsDto,
  ): Promise<PaginatedResult<any>> {
    const { cursor, limit = 20, search } = params;

    const where: Prisma.DepartmentWhereInput = {
      clubId,
      ...(search
        ? { name: { contains: search, mode: 'insensitive' as const } }
        : {}),
    };

    const items = await this.prisma.department.findMany({
      where,
      take: limit + 1,
      ...(cursor ? { cursor: { id: cursor }, skip: 1 } : {}),
      orderBy: { name: 'asc' },
      include: {
        _count: { select: { users: true } },
      },
    });

    const hasMore = items.length > limit;
    const data = hasMore ? items.slice(0, -1) : items;

    return {
      data,
      nextCursor: hasMore ? data[data.length - 1].id : null,
      hasMore,
    };
  }

  async findById(clubId: string, id: string) {
    const department = await this.prisma.department.findFirst({
      where: { id, clubId },
      include: {
        users: {
          select: { id: true, firstName: true, lastName: true, role: true },
        },
      },
    });

    if (!department) {
      throw new NotFoundException(`Department with id ${id} not found`);
    }
    return department;
  }

  async create(clubId: string, dto: CreateDepartmentDto) {
    return this.prisma.department.create({
      data: {
        clubId,
        name: dto.name,
        description: dto.description,
      },
    });
  }

  async update(clubId: string, id: string, dto: UpdateDepartmentDto) {
    await this.ensureExists(clubId, id);

    return this.prisma.department.update({
      where: { id },
      data: {
        ...(dto.name !== undefined ? { name: dto.name } : {}),
        ...(dto.description !== undefined
          ? { description: dto.description }
          : {}),
      },
    });
  }

  async remove(clubId: string, id: string) {
    await this.ensureExists(clubId, id);
    await this.prisma.department.delete({ where: { id } });
  }

  private async ensureExists(clubId: string, id: string): Promise<void> {
    const count = await this.prisma.department.count({
      where: { id, clubId },
    });
    if (count === 0) {
      throw new NotFoundException(`Department with id ${id} not found`);
    }
  }
}
