import { Injectable, NotFoundException } from '@nestjs/common';
import { PrismaService } from '../prisma/prisma.service';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
import * as bcrypt from 'bcrypt';

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

  async create(createUserDto: CreateUserDto, tenantId: number) {
    const hashedPassword = await bcrypt.hash(createUserDto.password, 10);
    const { roleIds, ...userData } = createUserDto;

    // 验证角色是否属于该租户
    if (roleIds && roleIds.length > 0) {
      const roles = await this.prisma.role.findMany({
        where: {
          id: { in: roleIds },
          tenantId,
        },
      });
      if (roles.length !== roleIds.length) {
        throw new NotFoundException('部分角色不存在或不属于该租户');
      }
    }

    return this.prisma.user.create({
      data: {
        ...userData,
        tenantId,
        password: hashedPassword,
        roles:
          roleIds && roleIds.length > 0
            ? {
                create: roleIds.map((roleId) => ({
                  roleId,
                })),
              }
            : undefined,
      },
      include: {
        roles: {
          include: {
            role: true,
          },
        },
      },
    });
  }

  async findAll(
    page: number = 1,
    pageSize: number = 10,
    tenantId?: number,
    keyword?: string,
  ) {
    const skip = (page - 1) * pageSize;
    const where: any = {};

    if (tenantId) {
      where.tenantId = tenantId;
    }

    // 支持关键字搜索（搜索用户名或昵称）
    if (keyword) {
      where.OR = [
        { username: { contains: keyword } },
        { nickname: { contains: keyword } },
        { email: { contains: keyword } },
      ];
    }

    const [list, total] = await Promise.all([
      this.prisma.user.findMany({
        where,
        skip,
        take: pageSize,
        include: {
          roles: {
            include: {
              role: true,
            },
          },
        },
        orderBy: { createTime: 'desc' },
      }),
      this.prisma.user.count({ where }),
    ]);

    return {
      list,
      total,
      page,
      pageSize,
    };
  }

  async findOne(id: number, tenantId?: number) {
    const where: any = { id };
    if (tenantId) {
      where.tenantId = tenantId;
    }

    const user = await this.prisma.user.findFirst({
      where,
      include: {
        roles: {
          include: {
            role: {
              include: {
                permissions: {
                  include: {
                    permission: true,
                  },
                },
              },
            },
          },
        },
      },
    });

    if (!user) {
      throw new NotFoundException('用户不存在');
    }

    return user;
  }

  async findByUsername(username: string, tenantId?: number) {
    const where: any = { username };
    if (tenantId) {
      where.tenantId = tenantId;
    }

    return this.prisma.user.findFirst({
      where,
      include: {
        roles: {
          include: {
            role: {
              include: {
                permissions: {
                  include: {
                    permission: true,
                  },
                },
              },
            },
          },
        },
      },
    });
  }

  async update(id: number, updateUserDto: UpdateUserDto, tenantId?: number) {
    const { roleIds, ...userData } = updateUserDto;
    const data: any = { ...userData };

    // 验证用户是否存在且属于该租户
    const existingUser = await this.findOne(id, tenantId);

    if (updateUserDto.password) {
      data.password = await bcrypt.hash(updateUserDto.password, 10);
    }

    // 如果提供了 roleIds，更新角色关联
    if (roleIds !== undefined && tenantId) {
      // 验证角色是否属于该租户
      const roles = await this.prisma.role.findMany({
        where: {
          id: { in: roleIds },
          tenantId,
        },
      });
      if (roles.length !== roleIds.length) {
        throw new NotFoundException('部分角色不存在或不属于该租户');
      }

      // 先删除所有现有角色关联
      await this.prisma.userRole.deleteMany({
        where: { userId: id },
      });

      // 创建新的角色关联
      if (roleIds.length > 0) {
        data.roles = {
          create: roleIds.map((roleId) => ({
            roleId,
          })),
        };
      }
    }

    return this.prisma.user.update({
      where: { id },
      data,
      include: {
        roles: {
          include: {
            role: true,
          },
        },
      },
    });
  }

  async remove(id: number, tenantId?: number) {
    // 验证用户是否存在且属于该租户
    await this.findOne(id, tenantId);
    
    return this.prisma.user.delete({
      where: { id },
    });
  }
}
