import { ConflictException, Get, Injectable, UnauthorizedException } from '@nestjs/common';
import { UserService } from '../user/user.service.js';
import * as bcrypt from 'bcrypt';
import { JwtService } from '@nestjs/jwt';
import { SignUpDto } from './dto/sign-up.dto.js';
import { UserEntity } from '../../entities/user.entity.js';
import { ValidateService } from '../../validate/validate.service.js';
@Injectable()
export class AuthenticationService {
  constructor(
    private usersService: UserService,
    private jwtService: JwtService,
    private validatService: ValidateService
  ) {}

  async signIn(
    username: string,
    pass: string,
  ): Promise<{ access_token: string }> {
    let user;
    if (username.includes("@"))
      user = await this.usersService.findOneByField('email', username);
    else
      user = await this.usersService.findOneByField('phone_number', username);
    if (!user)
      throw new UnauthorizedException("We can't find your user");
    const compare = await bcrypt.compare(pass, user.hash_password)
    if (!compare) {
      throw new UnauthorizedException("Wrong password");
    }
    const payload = { sub: user.id, username: user.full_name, roles: user.role};
    return {
      access_token: await this.jwtService.signAsync(payload),
    };
  }

  async signUp(
    signUpDto: SignUpDto,
  ): Promise<{ access_token: string }> {
    const { 
      full_name, 
      phone_number, 
      email, 
      password 
    } = signUpDto

    await this.validatService.checkExistField('email', email);
    await this.validatService.checkExistField('phone_number', phone_number)
    const hash_password = await bcrypt.hash(password, 10)

    const user = await this.usersService.create({
      full_name: full_name,
      phone_number: phone_number,
      email: email,
      password: hash_password
    })
    await this.usersService.save(user);

    const payload = { sub: user.id, username: user.full_name, role: user.role };
    const token = await this.jwtService.signAsync(payload)
    return {
      access_token: token
    };
  }
  
  async checkExistField(fieldName, fieldValue){
    if (fieldValue === null || fieldValue === undefined) {
      return;
    }
    const existingUser = await this.usersService.findOneByField(fieldName, fieldValue);
    if (existingUser) {
      throw new ConflictException(fieldName + ' is already taken');
    }
  }

  async getProfile(userId: string) {
    const user = await UserEntity.findOne({
      where: { id: userId }
    });
    const { hash_password, ...userWithoutHash } = user;
    return userWithoutHash;
  }
}