import {
  Controller,
  Get,
  Post,
  Patch,
  Delete,
  Body,
  Param,
  Query,
  UseGuards,
  ParseUUIDPipe,
  HttpCode,
  HttpStatus,
} from '@nestjs/common';
import {
  ApiTags,
  ApiOperation,
  ApiBearerAuth,
  ApiResponse,
  ApiParam,
} from '@nestjs/swagger';
import { ClientsService } from './clients.service';
import { JwtAuthGuard } from '../auth/guards/jwt-auth.guard';
import { RolesGuard } from '../auth/guards/roles.guard';
import { Roles, UserRole } from '../../common/decorators/roles.decorator';
import {
  CurrentUser,
  JwtPayload,
} from '../../common/decorators/current-user.decorator';
import {
  FindClientsDto,
  CreateClientDto,
  UpdateClientDto,
  CreateGoalDto,
  CreateInjuryDto,
} from './dto';

@ApiTags('Clients')
@ApiBearerAuth()
@Controller('clients')
@UseGuards(JwtAuthGuard)
export class ClientsController {
  constructor(private readonly clientsService: ClientsService) {}

  @Get()
  @ApiOperation({ summary: 'List clients with pagination and filters' })
  @ApiResponse({ status: 200, description: 'Paginated list of clients' })
  async findAll(
    @CurrentUser() user: JwtPayload,
    @Query() query: FindClientsDto,
  ) {
    const params = this.applyTrainerFilter(user, query);
    return this.clientsService.findAll(user.clubId, params);
  }

  @Get('sleeping')
  @UseGuards(RolesGuard)
  @Roles(
    UserRole.TRAINER,
    UserRole.COORDINATOR,
    UserRole.MANAGER,
    UserRole.RECEPTIONIST,
    UserRole.CLUB_ADMIN,
  )
  @ApiOperation({
    summary: 'List sleeping clients (active membership, no activity > 30 days)',
  })
  @ApiResponse({ status: 200, description: 'Paginated list of sleeping clients' })
  async findSleeping(
    @CurrentUser() user: JwtPayload,
    @Query() query: FindClientsDto,
  ) {
    const trainerFilter =
      user.role === UserRole.TRAINER ? user.sub : undefined;

    return this.clientsService.findSleeping(user.clubId, {
      ...query,
      trainerFilter,
    });
  }

  @Get(':id')
  @ApiOperation({ summary: 'Get client by ID with goals, injuries, memberships' })
  @ApiParam({ name: 'id', description: 'Client UUID' })
  @ApiResponse({ status: 200, description: 'Client details' })
  @ApiResponse({ status: 404, description: 'Client not found' })
  async findById(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    return this.clientsService.findById(user.clubId, id);
  }

  @Post()
  @UseGuards(RolesGuard)
  @Roles(
    UserRole.COORDINATOR,
    UserRole.MANAGER,
    UserRole.RECEPTIONIST,
    UserRole.CLUB_ADMIN,
  )
  @ApiOperation({ summary: 'Create a new client' })
  @ApiResponse({ status: 201, description: 'Client created' })
  @ApiResponse({ status: 403, description: 'Insufficient role' })
  async create(
    @CurrentUser() user: JwtPayload,
    @Body() dto: CreateClientDto,
  ) {
    return this.clientsService.create(user.clubId, dto);
  }

  @Patch(':id')
  @UseGuards(RolesGuard)
  @Roles(
    UserRole.TRAINER,
    UserRole.COORDINATOR,
    UserRole.MANAGER,
    UserRole.RECEPTIONIST,
    UserRole.CLUB_ADMIN,
  )
  @ApiOperation({ summary: 'Update an existing client' })
  @ApiParam({ name: 'id', description: 'Client UUID' })
  @ApiResponse({ status: 200, description: 'Client updated' })
  @ApiResponse({ status: 404, description: 'Client not found' })
  async update(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: UpdateClientDto,
  ) {
    return this.clientsService.update(user.clubId, id, dto);
  }

  @Delete(':id')
  @UseGuards(RolesGuard)
  @Roles(UserRole.MANAGER, UserRole.CLUB_ADMIN)
  @HttpCode(HttpStatus.NO_CONTENT)
  @ApiOperation({ summary: 'Delete a client' })
  @ApiParam({ name: 'id', description: 'Client UUID' })
  @ApiResponse({ status: 204, description: 'Client deleted' })
  @ApiResponse({ status: 404, description: 'Client not found' })
  async delete(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    return this.clientsService.delete(user.clubId, id);
  }

  @Post(':id/assign')
  @UseGuards(RolesGuard)
  @Roles(UserRole.COORDINATOR, UserRole.MANAGER)
  @ApiOperation({ summary: 'Assign a trainer to a client' })
  @ApiParam({ name: 'id', description: 'Client UUID' })
  @ApiResponse({ status: 200, description: 'Trainer assigned' })
  @ApiResponse({ status: 404, description: 'Client not found' })
  async assignTrainer(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
    @Body('trainerId', ParseUUIDPipe) trainerId: string,
  ) {
    return this.clientsService.assignTrainer(user.clubId, id, trainerId);
  }

  @Get(':id/goals')
  @ApiOperation({ summary: 'List goals for a client' })
  @ApiParam({ name: 'id', description: 'Client UUID' })
  @ApiResponse({ status: 200, description: 'List of client goals' })
  @ApiResponse({ status: 404, description: 'Client not found' })
  async findGoals(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    return this.clientsService.findGoals(user.clubId, id);
  }

  @Post(':id/goals')
  @UseGuards(RolesGuard)
  @Roles(
    UserRole.TRAINER,
    UserRole.COORDINATOR,
    UserRole.MANAGER,
    UserRole.CLUB_ADMIN,
  )
  @ApiOperation({ summary: 'Add a goal to a client' })
  @ApiParam({ name: 'id', description: 'Client UUID' })
  @ApiResponse({ status: 201, description: 'Goal created' })
  @ApiResponse({ status: 404, description: 'Client not found' })
  async createGoal(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: CreateGoalDto,
  ) {
    return this.clientsService.createGoal(user.clubId, id, dto);
  }

  @Get(':id/injuries')
  @ApiOperation({ summary: 'List injuries for a client' })
  @ApiParam({ name: 'id', description: 'Client UUID' })
  @ApiResponse({ status: 200, description: 'List of client injuries' })
  @ApiResponse({ status: 404, description: 'Client not found' })
  async findInjuries(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
  ) {
    return this.clientsService.findInjuries(user.clubId, id);
  }

  @Post(':id/injuries')
  @UseGuards(RolesGuard)
  @Roles(
    UserRole.TRAINER,
    UserRole.COORDINATOR,
    UserRole.MANAGER,
    UserRole.CLUB_ADMIN,
  )
  @ApiOperation({ summary: 'Add an injury record to a client' })
  @ApiParam({ name: 'id', description: 'Client UUID' })
  @ApiResponse({ status: 201, description: 'Injury created' })
  @ApiResponse({ status: 404, description: 'Client not found' })
  async createInjury(
    @CurrentUser() user: JwtPayload,
    @Param('id', ParseUUIDPipe) id: string,
    @Body() dto: CreateInjuryDto,
  ) {
    return this.clientsService.createInjury(user.clubId, id, dto);
  }

  /**
   * For TRAINER role, force the assignedTrainerId filter to their own user ID.
   * Other roles see all clients or use the provided filter.
   */
  private applyTrainerFilter(
    user: JwtPayload,
    query: FindClientsDto,
  ): FindClientsDto {
    if (user.role === UserRole.TRAINER) {
      return { ...query, assignedTrainerId: user.sub };
    }
    return query;
  }
}
