import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { BehaviorSubject, Observable } from 'rxjs';
import { environment } from 'src/environments/environment';
import { User } from '../model/user';

@Injectable({
  providedIn: 'root'
})
export class AuthService {

  private authInfoSubject: BehaviorSubject<User> = new BehaviorSubject(null as any);
  authInfo$: Observable<User> = this.authInfoSubject.asObservable();

  private token: string = '';

  constructor(private http: HttpClient, private router: Router) {
  }

  get isAdmin(): boolean {
    return this.user != null && this.user.role != null && this.user.role.id == 1;
  }

  isLoggedIn(): boolean {
    return this.authInfoSubject.value != null;
  }

  get user(): User {
    return this.authInfoSubject.value;
  }

  public async login(email: string, password: string): Promise<boolean> {
    return new Promise(resolve => {
      this.http.post(`${environment.apiUrl}auth/email/login`, { email, password }).subscribe((result: any) => {
      localStorage.setItem('accessToken', window.btoa(result['token']));
      this.authInfoSubject.next(result['user']);
      this.token = result['token'];
      resolve(true);
      }, error => {
        this.http.post(`${environment.apiUrl}auth/admin/email/login`,  { email, password }).subscribe((result: any) => {
          if (result && result['token']) {
            localStorage.setItem('accessToken', window.btoa(result['token']));
            this.authInfoSubject.next(result['user']);
            this.token = result['token'];
            resolve(true)
          }
        }, error => {
          resolve(false);
        })
      })
    })
  }

  getAuthToken(): string {
    return this.token;
  }

  async verifyAccessToken(token: string): Promise<boolean> {
    this.token = token;
    return new Promise(resolve => {
      this.http.get<User>(`${environment.apiUrl}auth/me`).subscribe(res => {
        if (res && res.firstName) {
          this.authInfoSubject.next(res);
          if ((res as any)['token']) {
            const token = (res as any)['token'];
            this.token = token;
            localStorage.setItem('accessToken', window.btoa(token));
          }
          return resolve(true);
        }
        return resolve(false);
        
      }, () => {
        return resolve(false);
      })
    })
    
  }

  logout() {
    this.authInfoSubject.next(null as any);
    localStorage.removeItem('accessToken');
    this.router.navigate(['auth'])
  }

  register(data: {email: string, password: string, firstName: string, lastName: string, linkPlayerId?: number}): Observable<any> {
    return this.http.post(`${environment.apiUrl}auth/email/register`, data);
  }

  forgotPassword(email: string): Observable<any> {
    return this.http.post(`${environment.apiUrl}auth/forgot/password`, { email });
  }

  resetPassword(hash: string, password: string): Observable<any> {
    return this.http.post(`${environment.apiUrl}auth/reset/password`, { hash, password });
  }

  async loginFromLocalStorage(suppressNavigation = false): Promise<boolean> {
    return new Promise<boolean>(async resolve => {
      const authToken = localStorage.getItem('accessToken');

      if (!authToken || authToken.length == 0) {
        if (!suppressNavigation) {
          this.router.navigate(['/auth']).then();
        }
        return resolve(false);
      }

      const accessToken = window.atob(authToken);
      

      const success = await this.verifyAccessToken(accessToken);
      resolve(success)
    })
  }
}
