import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { EventService } from './event.service';
import { of, firstValueFrom } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';
import { Router } from '@angular/router';
import { Preferences } from '@capacitor/preferences';
import { EnvService } from './env.service';
import { User } from '../models/user';
import { getAuth, signOut as firebaseSignOut } from 'firebase/auth';
import { getApps } from 'firebase/app';

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

  isLoggedIn = false;
  isVerified = false;
  isReported = false;
  userName: string = '';
  userRole: number = 0;
  userId: any = null;
  role: any;
  token: any;
  userInfo: any;
  private initPromise: Promise<void> | null = null;

    constructor(
      private http: HttpClient,
      private env: EnvService,
      private events: EventService,
      private router: Router

    ) { }
    loginWithFirebase(idToken: string) {
      return this.http.post(this.env.API_URL + 'auth/firebase',
        { firebase_token: idToken }
      ).pipe(
        tap((token: any) => {
          if (token['verified'] != null) {
            this.isVerified = true;
          }
          if (token['reported'] == 1) {
            this.isReported = true;
          }
          Preferences.set({ key: 'token', value: JSON.stringify(token) })
          .then(() => {
            console.log('Token Stored');
          }).catch(error => console.error('Error storing item', error));
          this.token = token;
          this.isLoggedIn = true;
          this.userRole = token['role'] ?? 0;
          this.events.publish('set_role', token['role']);
          return token;
        }),
      );
    }

    registerWithFirebase(idToken: string, name: string, phone: string, email: string) {
      return this.http.post(this.env.API_URL + 'auth/register',
        { firebase_token: idToken, name: name, phone: phone, email: email }
      ).pipe(
        tap((token: any) => {
          if (token['verified'] != null) {
            this.isVerified = true;
          }
          Preferences.set({ key: 'token', value: JSON.stringify(token) })
            .catch(error => console.error('Error storing item', error));
          this.token = token;
          this.isLoggedIn = true;
          this.events.publish('set_role', token['role']);
          return token;
        })
      );
    }
    logout() {
      this.clearSession();

      const tokenType = this.token?.['token_type'];
      const accessToken = this.token?.['access_token'];
      if (!tokenType || !accessToken) {
        return of(null);
      }

      const headers = new HttpHeaders({ 'Authorization': `${tokenType} ${accessToken}` });
      return this.http.get(this.env.API_URL + 'auth/logout', { headers }).pipe(
        catchError(() => of(null))
      );
    }

    initialize(): Promise<void> {
      if (!this.initPromise) {
        this.initPromise = this.runInitialize();
      }
      return this.initPromise;
    }

    private async runInitialize(): Promise<void> {
      await this.getToken();
      if (this.isLoggedIn) {
        try {
          await firstValueFrom(this.user());
        } catch {
          this.clearSession();
        }
      }
    }

    clearSession() {
      this.initPromise = null;
      if (getApps().length > 0) {
        firebaseSignOut(getAuth()).catch(() => {});
      }
      Preferences.remove({ key: 'token' });
      this.isLoggedIn = false;
      this.isVerified = false;
      this.userName = '';
      this.userRole = 0;
      delete this.token;
    }
    user() {
      if (!this.token?.['token_type'] || !this.token?.['access_token']) {
        return of(null);
      }
      const headers = new HttpHeaders({
        'Authorization': this.token["token_type"]+" "+this.token["access_token"]
      });
      return this.http.get<User>(this.env.API_URL + 'auth/user', { headers: headers })
      .pipe(
        tap((user: any) => {
          if (user['phone_verified_at'] != null) {
            this.isVerified = true;
          } else {
            this.isVerified = false;
          }
          if (user['reported'] == true) {
            this.isReported = true;
          } else {
            this.isReported = false;
          }
          this.userName = user['name'] ?? '';
          this.userRole = user['role_id'] ?? 0;
          this.userId = user['id'] ?? null;
          this.events.publish('set_role', user['role_id']);
          console.log("after login:", user);
        })
      )
    }
    async getToken() {
      try {
        const { value } = await Preferences.get({ key: 'token' });
        if (value) {
          this.token = JSON.parse(value);
          this.isLoggedIn = true;
          if (this.token['verified'] != null) {
            this.isVerified = true;
          }
          if (this.token['reported'] == 1) {
            this.isReported = true;
          }
        } else {
          this.isLoggedIn = false;
        }
      } catch (error) {
        this.token = null;
        this.isLoggedIn = false;
      }
    }
    verifyUser(phone_string: String) {
      const headers = new HttpHeaders({
        'Authorization': this.token["token_type"]+" "+this.token["access_token"]
      });
      return this.http.post(this.env.API_URL + 'auth/verify',
        { phone: phone_string }, { headers: headers });
    }

}
