import { inject, Injectable, signal } from '@angular/core';
import { AUTH_REPOSITORY_TOKEN } from '@app/infrastructure/authentification/auth-repository.token';
import { LoaderAction } from '@app/domain/loader-action.util';
import { ActionType } from '@app/domain/action-type.util';
import { ErrorResponse } from '@app/domain/error-response.util';
import { LoginUseCase } from '../../application/authentification/login.usecase';
import { RegisterUseCase } from '../../application/authentification/register.usecase';
import { LoginDto } from '@app/domain/authentification/dto/login-dto';
import { RegisterDto } from '@app/domain/authentification/dto/register-dto';
import { User } from '@app/domain/users/user.model';
import { AuthResponse } from '@app/domain/authentification/auth.repository';
import { ProfileDTO } from '@app/domain/profiles/dto/create-profile.dto';
import { ProfileFacade } from '../profiles/profile.facade';
import { SendVerificationEmailUsecase } from '../../application/authentification/send-verification-email.usecase';
import { LogoutUseCase } from '../../application/authentification/logout.usecase';
import { VerifyAuthenticatedUsecase } from '../../application/authentification/verify-authenticated.usecase';
import { VerifyEmailUseCase } from '../../application/authentification/verify-email.usecase';
import { GetCurrentUserUseCase } from '../../application/authentification/get-current-user.usecase';
import { SendRequestPasswordResetUsecase } from '../../application/authentification/send-request-password-reset.usecase';
import { FeedbackService } from '../shared/services/feedback.service';
import { first } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class AuthFacade {
  private readonly feedbackService = inject(FeedbackService);
  private readonly authRepository = inject(AUTH_REPOSITORY_TOKEN);

  private readonly profileFacade = new ProfileFacade();

  private readonly loginUseCase = new LoginUseCase(this.authRepository);
  private readonly registerUseCase = new RegisterUseCase(this.authRepository);
  private readonly logoutUseCase = new LogoutUseCase(this.authRepository);
  private readonly getUserUseCase = new GetCurrentUserUseCase(this.authRepository);
  private readonly sendVerificationEmailUseCase = new SendVerificationEmailUsecase(
    this.authRepository
  );
  private readonly verifyAuthenticatedUseCase = new VerifyAuthenticatedUsecase(this.authRepository);
  private readonly verifyEmailUseCase = new VerifyEmailUseCase(this.authRepository);

  private readonly senRequestPasswordResetUseCase = new SendRequestPasswordResetUsecase(
    this.authRepository
  );

  readonly isAuthenticated = signal<boolean>(false);
  readonly isEmailVerified = signal<boolean>(false);
  readonly isVerificationEmailSent = signal<boolean>(false);
  readonly isRequestPasswordSent = signal<boolean>(false);

  readonly user = signal<User | undefined>(undefined);
  readonly authResponse = signal<AuthResponse | undefined>(undefined);

  readonly loading = signal<LoaderAction>({ isLoading: false, action: ActionType.NONE });
  readonly error = signal<ErrorResponse>({
    action: ActionType.NONE,
    hasError: false,
    message: null,
  });

  login(loginDto: LoginDto) {
    this.handleError(ActionType.READ, false, null, true);
    let message = '';

    this.loginUseCase
      .execute(loginDto)
      .pipe(first())
      .subscribe({
        next: async (res: AuthResponse) => {
          this.authResponse.set(res);
          this.getCurrentUser();
          this.handleError(ActionType.READ, false, null, false);

          if (!this.authResponse()!.isValid && !this.authResponse()?.record.verified) {
            message = `Vous ne pouvez pas vous connecter sans valider la verification envoyé à cet adresse ${this.authResponse()?.record.email!}`;
            this.feedbackService.notify(ActionType.READ, `${message}`);
            return;
          }

          message = `Bienvenue parmi nous ${loginDto.email}!`;
          this.feedbackService.notify(ActionType.READ, `${message}`);
        },
        error: (err) => {
          this.handleError(ActionType.READ, true, err.message, false);
        },
      });
  }

  register(registerDto: RegisterDto) {
    this.handleError(ActionType.CREATE, false, null, true);
    let message = '';

    this.registerUseCase
      .execute(registerDto)
      .pipe(first())
      .subscribe({
        next: (user) => {
          this.getCurrentUser();
          this.sendVerificationEmail(registerDto.email);
          this.createDefaultProfile(user.id);

          message = `Votre compte a bien été crée avec succès !\n Un mail vous a été envoyé à l'adresse ${registerDto.email} pour confirmer votre inscription.`;
          this.feedbackService.notify(ActionType.CREATE, `${message}`);

          this.handleError(ActionType.CREATE, false, null, false);
        },
        error: (err) => {
          this.handleError(ActionType.CREATE, true, err.message, false);
        },
      });
  }

  logout() {
    this.logoutUseCase.execute();
    this.isAuthenticated.set(false);
    this.getCurrentUser();
  }

  verifyAuthenticatedUser() {
    this.isAuthenticated.set(this.verifyAuthenticatedUseCase.execute());
  }

  verifyEmail() {
    this.isEmailVerified.set(this.verifyEmailUseCase.execute());
  }

  getCurrentUser() {
    this.user.set(this.getUserUseCase.execute());
  }

  sendRequestPasswordReset(email: string) {
    this.handleError(ActionType.CREATE, false, null, true);

    let message = '';
    this.senRequestPasswordResetUseCase
      .execute(email)
      .pipe(first())
      .subscribe({
        next: (res) => {
          this.isRequestPasswordSent.set(res);
          this.handleError(ActionType.CREATE, false, null, false);
          message = `Un mail de réinitialisation vous a été envoyé à cette adresse mail : ${email}`;
          this.feedbackService.notify(ActionType.CREATE, `${message}`);
        },
        error: (err) => {
          this.handleError(ActionType.CREATE, true, err.message, false);
        },
      });
  }

  private sendVerificationEmail(email: string) {
    this.handleError(ActionType.CREATE, false, null, true);
    this.sendVerificationEmailUseCase
      .execute(email)
      .pipe(first())
      .subscribe({
        next: (res) => {
          this.isVerificationEmailSent.set(res);
          this.handleError(ActionType.CREATE, false, null, false);
        },
        error: (err) => {
          this.handleError(ActionType.CREATE, true, err.message, false);
        },
      });
  }

  private createDefaultProfile(userId: string) {
    const profileDto: ProfileDTO = {
      profession: 'Profession non renseignée',
      utilisateur: userId,
      reseaux: {
        facebook: '',
        github: '',
        instagram: '',
        linkedIn: '',
        web: '',
        x: '',
        youTube: '',
      },
    };

    this.profileFacade.create(profileDto);
  }

  private handleError(
    action: ActionType = ActionType.NONE,
    hasError: boolean,
    message: string | null = null,
    isLoading = false
  ) {
    this.error.set({ action, hasError, message });
    this.loading.set({ action, isLoading });
    if (hasError) {
      this.feedbackService.notify(ActionType.READ, message!, true);
    }
  }
}
