import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../../prisma/prisma.service';
import { FindClubsDto } from './dto/find-clubs.dto';
import { UpdateClubDto } from './dto/update-club.dto';
import { Prisma } from '@prisma/client';

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

const CLUB_INCLUDE = {
  license: true,
  clubModules: {
    select: { moduleId: true, enabled: true },
  },
  _count: {
    select: { users: true, clients: true },
  },
};

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

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

    const where: Prisma.ClubWhereInput = {
      ...(search
        ? {
            OR: [
              { name: { contains: search, mode: 'insensitive' as const } },
              { slug: { contains: search, mode: 'insensitive' as const } },
            ],
          }
        : {}),
      ...(isActive !== undefined ? { isActive } : {}),
    };

    const items = await this.prisma.club.findMany({
      where,
      take: limit + 1,
      ...(cursor ? { cursor: { id: cursor }, skip: 1 } : {}),
      orderBy: { createdAt: 'desc' },
      include: CLUB_INCLUDE,
    });

    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(id: string) {
    const club = await this.prisma.club.findUnique({
      where: { id },
      include: CLUB_INCLUDE,
    });

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

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

    return this.prisma.club.update({
      where: { id },
      data: {
        ...(dto.name !== undefined ? { name: dto.name } : {}),
        ...(dto.address !== undefined ? { address: dto.address } : {}),
        ...(dto.phone !== undefined ? { phone: dto.phone } : {}),
        ...(dto.email !== undefined ? { email: dto.email } : {}),
        ...(dto.logoUrl !== undefined ? { logoUrl: dto.logoUrl } : {}),
        ...(dto.timezone !== undefined ? { timezone: dto.timezone } : {}),
        ...(dto.isActive !== undefined ? { isActive: dto.isActive } : {}),
      },
      include: CLUB_INCLUDE,
    });
  }

  async softDelete(id: string) {
    await this.ensureExists(id);

    return this.prisma.club.update({
      where: { id },
      data: { isActive: false },
    });
  }

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