import { Component, OnDestroy, OnInit } from '@angular/core';
import {
  AbstractControl,
  FormControl,
  FormGroup,
  FormsModule,
  ReactiveFormsModule,
  Validators,
} from '@angular/forms';
import { AngularMaterialModule } from '../angular-material/angular-material.module';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { Router, RouterModule, ActivatedRoute } from '@angular/router';
import { UserService } from './user.service';
import { UntilDestroy, untilDestroyed } from '@ngneat/until-destroy';
import { AuthService } from '../auth/authService/auth.service';
import { Subscription, Subject } from 'rxjs';
import { take, takeUntil } from 'rxjs/operators';
import { User } from '../auth/model/user.model';
import { ScoreTableService } from '../score-table/score-table.service';
import { PendingActionsService } from '../score/pending-actions.service';
import { NotifierService } from '../shared/notifierService/notifier.service';
import { ProfilePhotoUploadComponent } from './profile-photo/profile-photo-upload/profile-photo-upload.component';
import { MatDividerModule } from '@angular/material/divider';
import { ProgressSpinnerComponent } from '../shared/progress-spinner/progress-spinner/progress-spinner.component';
import { HeaderComponent } from '../shared/header/header.component';
import {
  PasswordValidationType,
  passwordValidator,
} from '../shared/validation/passwordMatcherValidation';
import {
  hasNumberValidator,
  hasUpperCaseValidator,
} from '../shared/validation/passwordSaferValidation';
import { MatProgressSpinner } from '@angular/material/progress-spinner';
import { VerifiyWarnCardComponent } from './verify-email-warn-card/verify-email-warn-card.component';

@UntilDestroy()
@Component({
  selector: 'app-test',
  standalone: true,
  providers: [UserService, AuthService],
  templateUrl: './user-profile.component.html',
  styleUrl: './user-profile.component.css',
  imports: [
    CommonModule,
    AngularMaterialModule,
    FormsModule,
    ReactiveFormsModule,
    RouterModule,
    HttpClientModule,
    ProfilePhotoUploadComponent,
    MatDividerModule,
    ProgressSpinnerComponent,
    HeaderComponent,
    MatProgressSpinner,
    VerifiyWarnCardComponent,
  ],
})
export class UserProfileComponent implements OnInit, OnDestroy {
  userProfileForm!: FormGroup; // Form group to manage user profile data
  userProfilePhoto: string | undefined | null;
  userProfileSubscription!: Subscription; // Subscription to user profile changes
  user$ = this.userService.currentUserProfile$; // Observable of current user profile data
  dataLoaded: boolean = false;
  showProfile: boolean = true;
  hide: boolean = true;
  showSpinnerModule: boolean = false;
  isProfileOwner: boolean = false;
  isUpdatingPassword: boolean = false;
  private passwordValueChangesSubscription?: Subscription;
  private unsubscribe$ = new Subject<void>();
  showChangePassword: boolean = false;
  passwordForm: FormGroup;
  errorMessageCurrentPassword = '';
  errorMessageNewPassword = '';
  errorMessageConfirmPassword = '';

  constructor(
    private userService: UserService,
    private authService: AuthService,
    private router: Router,
    private route: ActivatedRoute,
    private scoreTableService: ScoreTableService,
    private pendingActionsService: PendingActionsService,
    private notifierService: NotifierService
  ) {
    this.dataLoaded = false;
    // Initialize the password form with form controls and validators from the new branch
    this.passwordForm = new FormGroup({
      currentPassword: new FormControl('', [Validators.required]),
      newPassword: new FormControl('', [
        Validators.required,
        Validators.minLength(10),
        Validators.maxLength(20),
        hasUpperCaseValidator(),
        hasNumberValidator(),
      ]),
      confirmNewPassword: new FormControl('', [Validators.required]),
    });

    // Apply the non-matching validator to the newPassword control
    const newPasswordControl = this.passwordForm.get('newPassword');
    const currentPasswordControl = this.passwordForm.get('currentPassword');
    const confirmNewPasswordControl =
      this.passwordForm.get('confirmNewPassword');

    if (
      newPasswordControl &&
      currentPasswordControl &&
      confirmNewPasswordControl
    ) {
      newPasswordControl.setValidators([
        Validators.required,
        Validators.minLength(10),
        Validators.maxLength(20),
        passwordValidator('currentPassword', PasswordValidationType.Different),
        hasUpperCaseValidator(),
        hasNumberValidator(),
      ]);

      // Apply the match validator to the confirmNewPassword control
      confirmNewPasswordControl.setValidators([
        Validators.required,
        passwordValidator('newPassword', PasswordValidationType.Match),
      ]);

      // Set up a subscription to the currentPassword field's valueChanges observable
      newPasswordControl.valueChanges.subscribe(() => {
        this.updateErrorMessage();
        confirmNewPasswordControl.updateValueAndValidity();
      });

      confirmNewPasswordControl.valueChanges.subscribe(() => {
        this.updateErrorMessage();
      });
    }
  }

  ngOnInit(): void {
    // Subscribe to query parameters
    this.route.queryParams
      .pipe(untilDestroyed(this))
      .subscribe(async (params) => {
        const score = params['score'];
        const uid = params['uid'];
        if (this.isUserVerified() && score && uid) {
          this.showProfile = false;
          this.scoreTableService.validateAndAddGame(score, uid);
          this.scoreTableService.setShowUserGames(true);
        } else if (score && uid) {
          this.showProfile = false;
          const uniqueId = this.pendingActionsService.saveTempQRCodeData({
            score,
            uid,
          });
          if (this.authService.getCurrentUser())
            this.pendingActionsService.addUserRefToQRCodeData(
              this.authService.getCurrentUser()?.uid!,
              uniqueId
            );
          this.router.navigate(['/score-table']);
        }

        // Subscribing to the user profile changes to update component properties
        this.userProfileSubscription = this.user$.subscribe((userProfile) => {
          this.userProfilePhoto = userProfile?.photoUrl;
        });
      });

    // Initializing the user profile form
    this.initForm();

    // Subscribe to route params
    this.route.params.pipe(untilDestroyed(this)).subscribe((params) => {
      this.initUserProfile(params['id']);
    });
  }

  // Function to save the updated profile data
  saveProfile() {
    this.showSpinnerModule = true;
    this.authService.currentUser$.pipe(take(1)).subscribe((user) => {
      if (user) {
        // Check that the user is not null
        const profileData = this.userProfileForm.value;
        const updatedUser: User = {
          uid: user.uid,
          firmenposition: profileData.firmenposition,
          // Include other fields as needed
        };
        this.userService.updateUser(updatedUser).subscribe();
        setTimeout(() => (this.showSpinnerModule = false), 1000);
        this.notifierService.showNotification(
          'Firmenposition erfolgreich aktualisiert.',
          'OK'
        );
      }
    });
  }

  // Function to handle logout
  onLogout() {
    // Dismiss any open notifications
    this.notifierService.dismissNotification();
    this.authService.logout().subscribe(() => {
      this.router.navigate(['/login']);
    });
    this.unsubscribe$.next();
  }

  ngOnDestroy(): void {
    // Unsubscribing from subscriptions to prevent memory leaks
    if (this.userProfileSubscription) {
      this.userProfileSubscription.unsubscribe();
    }
    if (this.passwordValueChangesSubscription) {
      this.passwordValueChangesSubscription.unsubscribe();
    }
    this.unsubscribe$.next();
    this.unsubscribe$.complete();
  }

  // Function to update the user's password
  updatePassword() {
    if (!this.passwordForm.valid) {
      return;
    }
    const currentUser = this.authService.getCurrentUser();
    if (!currentUser) {
      this.notifierService.showNotification(
        'Kein Benutzer angemeldet. Bitte melde dich an.',
        'OK'
      );
      return;
    }

    this.isUpdatingPassword = true;
    const currentPassword = this.passwordForm.value.currentPassword;
    const newPassword = this.passwordForm.value.newPassword;

    this.userService
      .updatePassword(currentPassword, newPassword)
      .pipe(takeUntil(this.unsubscribe$))
      .subscribe({
        next: () => {
          this.notifierService.showNotification(
            'Das Passwort wurde geändert.',
            'OK'
          );
          this.passwordForm.reset();
          this.showChangePassword = false;
          this.isUpdatingPassword = false;
        },
        error: (error) => {
          this.isUpdatingPassword = false;
          if (error.code === 'auth/invalid-credential') {
            this.notifierService.showNotification(
              'Das aktuelle Passwort ist falsch!',
              'OK'
            );
          } else {
            console.error('Error updating password:', error);
            this.notifierService.showNotification(
              'Bitte versuche es in 5 Min nochmal!',
              'OK'
            );
          }
        },
      });
  }

  isUserVerified() {
    return this.authService.getCurrentUser()?.emailVerified;
  }

  initForm() {
    this.userProfileForm = new FormGroup({
      uid: new FormControl(null),
      name: new FormControl(''),
      email: new FormControl(''),
      firmenposition: new FormControl(''),
      wins: new FormControl(''),
      //New Password validation
      currentPassword: new FormControl('', [
        Validators.required,
        Validators.minLength(10),
      ]),
      newPassword: new FormControl('', [
        Validators.required,
        Validators.minLength(10),
        Validators.maxLength(20),
      ]),
      confirmNewPassword: new FormControl('', [
        Validators.required,
        passwordValidator('newPassword', PasswordValidationType.Match),
      ]),
    });
  }

  updateForm(user: User | null) {
    if (user) {
      this.userProfileForm.patchValue({
        name: user?.firstName + ' ' + user?.lastName,
        ...user,
      });
      this.setProfilePhoto(user.uid);
    }
  }

  initUserProfile(uid: string) {
    this.user$.pipe(untilDestroyed(this)).subscribe(async (user) => {
      this.isProfileOwner = uid ? uid === user?.uid : true;
      if (this.isProfileOwner) {
        this.updateForm(user);
      } else {
        this.userService
          .getUserProfile(uid)
          .pipe(untilDestroyed(this))
          .subscribe(async (user) => {
            this.updateForm(user);
          });
      }
    });
  }

  setProfilePhoto(uid: string) {
    this.userService
      .getPhotoUrl(uid)
      .then((downloadURL) => {
        this.userProfilePhoto = downloadURL;
      })
      .finally(() => {
        this.dataLoaded = true;
      });
  }

  isCompanyAtos() {
    const email = this.userProfileForm.controls['email'].value;
    return email.includes('atos.net');
  }

  updateErrorMessage() {
    const currentPasswordControl = this.userProfileForm.get('currentPassword');
    const newPasswordControl = this.passwordForm.get('newPassword');
    const confirmNewPasswordControl =
      this.passwordForm.get('confirmNewPassword');

    this.errorMessageCurrentPassword = currentPasswordControl?.hasError(
      'required'
    )
      ? 'Aktuelles Passwort eingeben.'
      : '';
    this.errorMessageNewPassword =
      this.getNewPasswordErrorMessage(newPasswordControl);
    this.errorMessageConfirmPassword = this.getConfirmPasswordErrorMessage(
      confirmNewPasswordControl
    );
  }

  private getNewPasswordErrorMessage(control: AbstractControl | null): string {
    if (control?.hasError('required')) {
      return 'Neues Passwort eingeben.';
    } else if (control?.hasError('minlength')) {
      return 'Das Passwort muss mindestens 10 Zeichen lang sein.';
    } else if (control?.hasError('maxlength')) {
      return 'Das Passwort darf maximal 20 Zeichen lang sein.';
    } else if (control?.hasError('passwordsSame')) {
      return 'Das neue Passwort muss sich vom aktuellen Passwort unterscheiden.';
    } else if (
      control?.hasError('hasNumber') &&
      control?.hasError('hasUpperCase')
    ) {
      return 'Mind. 1 Großbuchstaben und 1 Zahl.';
    } else if (control?.hasError('hasUpperCase')) {
      return 'Mind. 1 Großbuchstaben.';
    } else if (control?.hasError('hasNumber')) {
      return 'Mind. 1 Zahl.';
    }
    return '';
  }

  private getConfirmPasswordErrorMessage(
    control: AbstractControl | null
  ): string {
    if (control?.hasError('required')) {
      return 'Passwortbestätigung eingeben.';
    } else if (control?.hasError('passwordMismatch')) {
      return 'Die eingegebenen Passwörter stimmen nicht überein.';
    }
    return '';
  }
}
