import {
  BadRequestException,
  Body,
  Controller,
  Delete,
  ForbiddenException,
  NotFoundException,
  Get,
  Param,
  Post,
  Put,
  Request,
  UseGuards,
  Query,
} from '@nestjs/common';
import { UserService } from './user.service';
import { CombinedAuthGuard } from '../auth/combined-auth.guard';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import { I18nService } from '../i18n/i18n.service';
import { UserRole } from './user-role.enum';
import { UserSettingService } from './user-setting.service';
import { ApiTags, ApiBearerAuth, ApiOperation, ApiResponse, ApiQuery } from '@nestjs/swagger';

@ApiTags('Users')
@Controller('users')
@UseGuards(CombinedAuthGuard)
export class UserController {
  constructor(
    private readonly userService: UserService,
    private readonly i18nService: I18nService,
    private readonly userSettingService: UserSettingService,
  ) { }

  // --- API Key Management ---
  @Get('api-key')
  async getApiKey(@Request() req) {
    const apiKey = await this.userService.getOrCreateApiKey(req.user.id);
    return { apiKey };
  }

  @Post('api-key/rotate')
  async rotateApiKey(@Request() req) {
    const apiKey = await this.userService.regenerateApiKey(req.user.id);
    return { apiKey };
  }

  // --- Personal Settings ---
  @Get('settings')
  async getSettings(@Request() req) {
    return this.userSettingService.getByUser(req.user.id);
  }

  @Put('settings/language')
  async updateLanguage(@Request() req, @Body() body: { language: string }) {
    if (!body.language) throw new BadRequestException('language is required');
    return this.userSettingService.update(req.user.id, body.language);
  }

  // --- Profile ---
  @Get('profile')
  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: '获取用户资料' })
  @ApiResponse({ status: 200, description: '返回用户资料' })
  async getProfile(@Request() req: any) {
    return this.userService.findOneById(req.user.id);
  }

  @Get('tenants')
  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: '获取用户所属的租户列表' })
  @ApiResponse({ status: 200, description: '返回租户列表' })
  async getMyTenants(@Request() req: any) {
    return this.userService.getUserTenants(req.user.id);
  }

  @Get('me')
  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: '获取当前登录用户信息' })
  @ApiResponse({ status: 200, description: '返回当前用户信息' })
  async getMe(@Request() req) {
    const user = await this.userService.findOneById(req.user.id);
    if (!user) throw new NotFoundException();

    let isNotebookEnabled = true;
    if (user.tenantId) {
      const settings = await this.userService.getTenantSettings(user.tenantId);
      isNotebookEnabled = settings?.isNotebookEnabled ?? true;
    }

    const tenantName = user.tenantMembers?.[0]?.tenant?.name || 'Default';

    return {
      id: user.id,
      username: user.username,
      displayName: user.displayName,
      role: user.isAdmin ? UserRole.SUPER_ADMIN : UserRole.USER,
      tenantId: user.tenantId,
      tenantName,
      isAdmin: user.isAdmin,
      isNotebookEnabled,
    };
  }

  @Get()
  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: '获取用户列表', description: '管理员专用，获取所有用户或租户内的用户' })
  @ApiQuery({ name: 'page', required: false, description: '页码' })
  @ApiQuery({ name: 'limit', required: false, description: '每页数量' })
  @ApiResponse({ status: 200, description: '返回用户列表' })
  @ApiResponse({ status: 403, description: '权限不足' })
  async findAll(
    @Request() req,
    @Query('page') page?: string,
    @Query('limit') limit?: string,
  ) {
    const callerRole = req.user.role;
    if (callerRole !== UserRole.SUPER_ADMIN && callerRole !== UserRole.TENANT_ADMIN) {
      throw new ForbiddenException(this.i18nService.getErrorMessage('adminOnlyViewList'));
    }

    const p = page ? parseInt(page) : undefined;
    const l = limit ? parseInt(limit) : undefined;

    if (callerRole === UserRole.SUPER_ADMIN) {
      return this.userService.findAll(p, l);
    } else {
      return this.userService.findByTenantId(req.user.tenantId, p, l);
    }
  }

  @Put('password')
  @ApiBearerAuth('JWT')
  @ApiOperation({ summary: '修改当前用户密码' })
  @ApiResponse({ status: 200, description: '密码修改成功' })
  @ApiResponse({ status: 400, description: '密码不符合要求' })
  async changePassword(
    @Request() req,
    @Body() body: { currentPassword: string; newPassword: string },
  ) {
    const { currentPassword, newPassword } = body;

    if (!currentPassword || !newPassword) {
      throw new BadRequestException(this.i18nService.getErrorMessage('passwordsRequired'));
    }

    if (newPassword.length < 6) {
      throw new BadRequestException(this.i18nService.getErrorMessage('newPasswordMinLength'));
    }

    return this.userService.changePassword(
      req.user.id,
      currentPassword,
      newPassword,
    );
  }

  @Post()
  async createUser(
    @Request() req,
    @Body() body: CreateUserDto,
  ) {
    const callerRole = req.user.role;
    if (callerRole !== UserRole.SUPER_ADMIN && callerRole !== UserRole.TENANT_ADMIN) {
      throw new ForbiddenException(this.i18nService.getErrorMessage('adminOnlyCreateUser'));
    }

    const { username, password } = body;

    if (!username || !password) {
      throw new BadRequestException(this.i18nService.getErrorMessage('usernamePasswordRequired'));
    }

    if (password.length < 6) {
      throw new BadRequestException(this.i18nService.getErrorMessage('passwordMinLength'));
    }

    // All new global users default to non-admin. 
    // Elevation to Super Admin status is handled separately.
    let isAdmin = false;

    if (callerRole === UserRole.SUPER_ADMIN) {
      isAdmin = false;
    } else if (callerRole === UserRole.TENANT_ADMIN) {
      isAdmin = false;
    }

    // Pass the calculated params to the service
    return this.userService.createUser(username, password, isAdmin, req.user.tenantId, body.displayName);
  }

  @Put(':id')
  async updateUser(
    @Request() req,
    @Body() body: UpdateUserDto,
    @Param('id') id: string,
  ) {
    const callerRole = req.user.role;
    if (callerRole !== UserRole.SUPER_ADMIN && callerRole !== UserRole.TENANT_ADMIN) {
      throw new ForbiddenException(this.i18nService.getErrorMessage('adminOnlyUpdateUser'));
    }

    // Get user info to update
    const userToUpdate = await this.userService.findOneById(id);
    if (!userToUpdate) {
      throw new NotFoundException(this.i18nService.getErrorMessage('userNotFound'));
    }

    if (callerRole === 'TENANT_ADMIN' && userToUpdate.tenantId !== req.user.tenantId) {
      throw new ForbiddenException('Cannot modify users outside your tenant');
    }

    // Prevent modifying the builtin admin account
    if (userToUpdate.username === 'admin') {
      throw new ForbiddenException(this.i18nService.getErrorMessage('cannotModifyBuiltinAdmin'));
    }

    // Role modification is now obsolete on global level. 
    // If Admin wants to elevate, they set isAdmin property directly.
    if (body.isAdmin !== undefined && userToUpdate.isAdmin !== body.isAdmin) {
      if (callerRole !== UserRole.SUPER_ADMIN) {
        throw new ForbiddenException('Only Super Admins can change user admin status.');
      }
    }

    // Validate password length if provided
    if (body.password && body.password.length < 6) {
      throw new BadRequestException(this.i18nService.getErrorMessage('passwordMinLength'));
    }

    return this.userService.updateUser(id, body);
  }

  @Delete(':id')
  async deleteUser(
    @Request() req,
    @Param('id') id: string,
  ) {
    const callerRole = req.user.role;
    if (callerRole !== UserRole.SUPER_ADMIN && callerRole !== UserRole.TENANT_ADMIN) {
      throw new ForbiddenException(this.i18nService.getErrorMessage('adminOnlyDeleteUser'));
    }

    // Prevent admin from deleting themselves
    if (req.user.id === id) {
      throw new BadRequestException(this.i18nService.getErrorMessage('cannotDeleteSelf'));
    }

    // Get user info to delete
    const userToDelete = await this.userService.findOneById(id);
    if (!userToDelete) {
      throw new NotFoundException(this.i18nService.getErrorMessage('userNotFound'));
    }

    if (callerRole === 'TENANT_ADMIN' && userToDelete.tenantId !== req.user.tenantId) {
      throw new ForbiddenException('Cannot delete users outside your tenant');
    }

    // Block deletion of built-in admin account
    if (userToDelete.username === 'admin') {
      throw new ForbiddenException(this.i18nService.getErrorMessage('cannotDeleteBuiltinAdmin'));
    }

    return this.userService.deleteUser(id);
  }
}
