import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import * as argon2 from 'argon2';
import { User } from '@prisma/client';

import { DatabaseService } from '../database/database.service';
import { UserCreateInput } from '../@generated/prisma-nestjs-graphql';

@Injectable()
export class AuthenticationService {
  constructor(
    private readonly $jwtService: JwtService,
    private readonly $database: DatabaseService
  ) {}

  public async validateUser(
    email: string,
    password: string
  ): Promise<any | null> {
    const user = await this.$database.user.findUnique({
      where: {
        email
      },
      select: {
        id: true,
        email: true,
        passwordHash: true,
        role: true
      }
    });

    if (user?.passwordHash) {
      const isValidPassword = await argon2.verify(user.passwordHash, password);

      if (isValidPassword) {
        const { passwordHash, ...result } = user;
        return result;
      }
    }

    return null;
  }

  public async login(
    user: User,
    allowRefresh: boolean
  ): Promise<{ accessToken: string }> {
    const payload = {
      email: user.email,
      sub: user.id,
      role: user.role,
      allowRefresh
    };

    return {
      accessToken: this.$jwtService.sign(payload)
    };
  }

  public async register(
    data: UserCreateInput
  ): Promise<{ accessToken: string }> {
    const user = await this.$database.user.create({ data });

    const payload = {
      email: user.email,
      sub: user.id,
      role: user.role,
      allowRefresh: false
    };

    return {
      accessToken: this.$jwtService.sign(payload)
    };
  }
}
