import { BadRequestException, Body, Controller, Get, HttpCode, Param, ParseIntPipe, Patch, Post, Query } from '@nestjs/common';
import { Throttle } from '@nestjs/throttler';
import { z } from 'zod';
import {
  createUserSchema,
  updateUserSchema,
  listUsersQuerySchema,
  type CreateUserInput,
  type AuthUser,
} from '@vihar/shared';
import { UsersService } from './users.service';
import { ZodValidationPipe } from '../../common/pipes/zod-validation.pipe';
import { CurrentUser, RequiresCaptain } from '../../common/decorators/auth.decorators';

const resetPasswordSchema = z.object({
  password: z.string().min(8).max(200),
});

@Controller('users')
@RequiresCaptain()
export class UsersController {
  constructor(private readonly users: UsersService) {}

  @Get()
  async list(
    @CurrentUser() user: AuthUser,
    @Query(new ZodValidationPipe(listUsersQuerySchema)) query: ReturnType<typeof listUsersQuerySchema.parse>,
  ) {
    if (!user.cityId) throw new BadRequestException('No city scope');
    return this.users.list(user.cityId, query);
  }

  @Get(':id')
  async get(@CurrentUser() user: AuthUser, @Param('id', ParseIntPipe) id: number) {
    if (!user.cityId) throw new BadRequestException('No city scope');
    return this.users.getById(user.cityId, id);
  }

  @Post()
  async create(
    @CurrentUser() user: AuthUser,
    @Body(new ZodValidationPipe(createUserSchema)) input: CreateUserInput,
  ) {
    if (!user.cityId) throw new BadRequestException('No city scope');
    return this.users.create(user.cityId, user.userId, input);
  }

  @Patch(':id')
  async update(
    @CurrentUser() user: AuthUser,
    @Param('id', ParseIntPipe) id: number,
    @Body(new ZodValidationPipe(updateUserSchema)) input: Record<string, unknown>,
  ) {
    if (!user.cityId) throw new BadRequestException('No city scope');
    return this.users.update(user.cityId, id, user.userId, input);
  }

  @Post(':id/reset-password')
  @HttpCode(204)
  @Throttle({ default: { limit: 10, ttl: 60 * 60 * 1000 } })
  async resetPassword(
    @CurrentUser() user: AuthUser,
    @Param('id', ParseIntPipe) id: number,
    @Body(new ZodValidationPipe(resetPasswordSchema)) body: { password: string },
  ) {
    if (!user.cityId) throw new BadRequestException('No city scope');
    await this.users.resetPassword(user.cityId, id, body.password);
  }
}
