import { ListProfilesUseCase } from '@app/usecase/profiles/list-profiles.usecase';
import { inject, Injectable, signal } from '@angular/core';
import { PROFILE_REPOSITORY_TOKEN } from '@app/infrastructure/profiles/profile-repository.token';
import { Profile } from '@app/domain/profiles/profile.model';
import { ProfilePresenter } from '@app/ui/profiles/profile.presenter';
import { ProfileViewModel } from '@app/ui/profiles/profile.presenter.model';
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 { CreateProfileUseCase } from '@app/usecase/profiles/create-profile.usecase';
import { UpdateProfileUseCase } from '@app/usecase/profiles/update-profile.usecase';
import { GetProfileUseCase } from '@app/usecase/profiles/get-profile.usecase';
import { ProfileDTO } from '@app/domain/profiles/dto/create-profile.dto';
import { AuthService } from '@app/core/services/authentication/auth.service';

@Injectable({
  providedIn: 'root',
})
export class ProfileFacade {
  private profileRepository = inject(PROFILE_REPOSITORY_TOKEN);
  protected readonly authService = inject(AuthService);

  private listUseCase = new ListProfilesUseCase(this.profileRepository);
  private createUseCase = new CreateProfileUseCase(this.profileRepository);
  private updateUseCase = new UpdateProfileUseCase(this.profileRepository);
  private getUseCase = new GetProfileUseCase(this.profileRepository);

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

  load(search?: string) {
    this.handleError(ActionType.READ, false, null, true);

    this.listUseCase.execute({ search }).subscribe({
      next: (profiles) => {
        this.profiles.set(ProfilePresenter.toViewModels(profiles));
        this.handleError(ActionType.READ, false, null, false);
      },
      error: (err) => {
        this.handleError(ActionType.READ, false, err, false);
      },
    });
  }

  loadOne(userId: string) {
    this.handleError(ActionType.READ, false, null, true);

    this.getUseCase.execute(userId).subscribe({
      next: (profile: Profile) => {
        this.profile.set(ProfilePresenter.toViewModel(profile));
        this.handleError(ActionType.READ, false, null, false);
      },
      error: (err) => {
        this.handleError(ActionType.READ, false, err, false);
      },
    });
  }

  create(profileDto: ProfileDTO) {
    this.handleError(ActionType.CREATE, false, null, true);

    this.createUseCase.execute(profileDto).subscribe({
      next: (profile: Profile) => {
        this.profile.set(ProfilePresenter.toViewModel(profile));
        this.handleError(ActionType.CREATE, false, null, false);
      },
      error: (err) => {
        this.handleError(ActionType.CREATE, false, err, false);
      },
    });
  }

  update(profileId: string, profile: Partial<Profile>) {
    this.handleError(ActionType.UPDATE, false, null, true);

    this.updateUseCase.execute(profileId, profile).subscribe({
      next: (profile: Profile) => {
        this.profile.set(ProfilePresenter.toViewModel(profile));
        this.authService.updateUser();
        this.handleError(ActionType.UPDATE, false, null, false);
      },
      error: (err) => {
        this.handleError(ActionType.UPDATE, false, err, false);
      },
    });
  }

  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 });
  }
}
