import {
  BadRequestException,
  Injectable,
  UnauthorizedException,
  InternalServerErrorException,
} from '@nestjs/common';
import { UsuariosService } from 'src/usuarios/usuarios.service';
import * as bcrypt from 'bcryptjs';
import { LoginDto } from './dto/login.dto';
import { CreateUsuarioDto } from 'src/usuarios/dto/create-usuario.dto';
import { JwtService } from '@nestjs/jwt';
import { UpdateUsuarioDto } from 'src/usuarios/dto/update-usuario.dto';

@Injectable()
export class AuthService {
  constructor(
    private readonly usuarioService: UsuariosService,
    private readonly jwtService: JwtService,
  ) {}

  async update(registroDto: UpdateUsuarioDto, id_User: number) {
    const update_data = await this.usuarioService.actualizarUsuario(id_User, {
      nombre: registroDto.nombre,
      contraseñaN: registroDto.contraseñaN,
      id_tipo_usuario: registroDto.tipoUsuario,
      contraseñaV: registroDto.contraseñaV,
    });
    return update_data;
  }

  async findAll() {
    return await this.usuarioService.usuarios();
  }

  async registro({ nombre, contraseña, tipoUsuario }: CreateUsuarioDto) {
    const usuario = await this.usuarioService.findOneByName(nombre);
    if (usuario) {
      throw new BadRequestException('Nombre de usuario ya existente');
    }

    try {
      const salt = await bcrypt.genSalt(10);
      const hashedContraseña = await bcrypt.hash(contraseña, salt);

      await this.usuarioService.create({
        nombre,
        contraseña: hashedContraseña,
        tipoUsuario,
      });

      return {
        message: 'Usuario registrado exitosamente',
      };
    } catch (error) {
      throw new InternalServerErrorException('Error al crear el usuario');
    }
  }

  async registroMasivo(usuarios: CreateUsuarioDto[]) {
    let resultados: string[] = [];

    for (const usuario of usuarios) {
      const creado = await this.registro(usuario);
      resultados.push(creado.message);
    }

    return resultados;
  }

  async login({ nombre, contraseña }: LoginDto) {
    const usuario = await this.usuarioService.findOneByName(nombre);
    if (!usuario) {
      throw new UnauthorizedException('Usuario no encontrado');
    }

    const contraseñaValida = await bcrypt.compare(
      contraseña,
      usuario.contraseña,
    );

    if (!contraseñaValida) {
      throw new UnauthorizedException('Contraseña inválida');
    }

    const dataUser = {
      id: usuario.id_usuario,
      nombre: usuario.nombre,
      tipoUsuario: usuario.tipoUsuario.id_tipo_usuario,
    };

    const token = this.jwtService.sign(dataUser);

    return {
      token,
    };
  }
}
