import { Injectable, NotFoundException } from '@nestjs/common';
import * as bcrypt from 'bcrypt';
import { RoleCode } from '@prisma/client';
import { PrismaService } from '../../prisma/prisma.service';
import { UpdateUserDto } from './users.dto';

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

  async list(tenantId: string | null) {
    return this.prisma.user.findMany({
      where: tenantId ? { roles: { some: { tenantId } } } : undefined,
      select: {
        id: true,
        email: true,
        phone: true,
        firstName: true,
        lastName: true,
        status: true,
        createdAt: true,
        roles: { include: { role: true } },
      },
      take: 200,
    });
  }

  async findOne(id: string) {
    const user = await this.prisma.user.findUnique({
      where: { id },
      include: { roles: { include: { role: true } } },
    });
    if (!user) throw new NotFoundException();
    const { passwordHash: _p, mfaSecret: _m, ...safe } = user;
    return safe;
  }

  async createWithRole(input: {
    email: string;
    password: string;
    firstName?: string;
    lastName?: string;
    phone?: string;
    roleCode: RoleCode;
    tenantId?: string | null;
    scopeComplexId?: string | null;
  }) {
    const passwordHash = await bcrypt.hash(input.password, 10);
    const role = await this.prisma.role.findUnique({ where: { code: input.roleCode } });
    if (!role) throw new NotFoundException(`Role ${input.roleCode} not found`);

    return this.prisma.user.create({
      data: {
        email: input.email,
        passwordHash,
        firstName: input.firstName,
        lastName: input.lastName,
        phone: input.phone,
        roles: {
          create: {
            roleId: role.id,
            tenantId: input.tenantId ?? null,
            scopeComplexId: input.scopeComplexId ?? null,
          },
        },
      },
      include: { roles: { include: { role: true } } },
    });
  }

  async update(id: string, dto: UpdateUserDto) {
    await this.findOne(id);
    const user = await this.prisma.user.update({
      where: { id },
      data: {
        firstName: dto.firstName,
        lastName: dto.lastName,
        phone: dto.phone,
        ...(dto.status ? { status: dto.status as any } : {}),
      },
      include: { roles: { include: { role: true } } },
    });
    const { passwordHash: _p, mfaSecret: _m, ...safe } = user;
    return safe;
  }

  async deactivate(id: string) {
    await this.findOne(id);
    await this.prisma.user.update({
      where: { id },
      data: { status: 'DISABLED' },
    });
    return { deleted: true };
  }
}
