import { Controller, Get, Put, Patch, Body } from "@nestjs/common";
import {
  ApiTags,
  ApiBearerAuth,
  ApiOperation,
  ApiOkResponse,
} from "@nestjs/swagger";
import { BaseController } from "../../common/base";
import { UsersService } from "./users.service";
import {
  CreateUserDto,
  UpdateUserDto,
  UpdateProfileDto,
  ChangePasswordDto,
} from "./dto/user.dto";
import { CurrentUser, Roles } from "../../common/decorators";
import {
  ApiResponse,
  createSuccessResponse,
} from "../../common/types/api-response.type";
import { User } from "@prisma/client";

import { plainToInstance } from "class-transformer";
import { UserResponseDto } from "./dto/user.dto";

interface AuthenticatedUser {
  id: string;
  email: string;
  role: string;
}

@ApiTags("Users")
@ApiBearerAuth()
@Controller("users")
export class UsersController extends BaseController<
  User,
  CreateUserDto,
  UpdateUserDto
> {
  constructor(private readonly usersService: UsersService) {
    super(usersService, "User");
  }

  @Get("me")
  @ApiOperation({ summary: "Get current authenticated user profile" })
  @ApiOkResponse({ type: UserResponseDto })
  async getMe(
    @CurrentUser() user: AuthenticatedUser,
  ): Promise<ApiResponse<UserResponseDto>> {
    const fullUser = await this.usersService.findOneWithDetails(user.id);
    return createSuccessResponse(
      plainToInstance(UserResponseDto, fullUser),
      "User profile retrieved successfully",
    );
  }

  @Put("me")
  @ApiOperation({ summary: "Update current user profile" })
  @ApiOkResponse({ type: UserResponseDto })
  async updateMe(
    @CurrentUser() user: AuthenticatedUser,
    @Body() dto: UpdateProfileDto,
  ): Promise<ApiResponse<UserResponseDto>> {
    const updatedUser = await this.usersService.updateProfile(user.id, dto);
    return createSuccessResponse(
      plainToInstance(UserResponseDto, updatedUser),
      "User profile updated successfully",
    );
  }

  @Patch("me/password")
  @ApiOperation({ summary: "Change current user password" })
  @ApiOkResponse({ description: "Password changed successfully" })
  async changePassword(
    @CurrentUser() user: AuthenticatedUser,
    @Body() dto: ChangePasswordDto,
  ): Promise<ApiResponse<null>> {
    await this.usersService.changePassword(
      user.id,
      dto.currentPassword,
      dto.newPassword,
    );
    return createSuccessResponse(null, "Password changed successfully");
  }

  // Override create to require admin role
  @Roles("superadmin")
  async create(
    ...args: Parameters<
      BaseController<User, CreateUserDto, UpdateUserDto>["create"]
    >
  ) {
    return super.create(...args);
  }

  // Override delete to require admin role
  @Roles("superadmin")
  async delete(
    ...args: Parameters<
      BaseController<User, CreateUserDto, UpdateUserDto>["delete"]
    >
  ) {
    return super.delete(...args);
  }
}
