import { Component, OnDestroy, OnInit } from '@angular/core';
import { AngularMaterialModule } from '../../angular-material/angular-material.module';
import {
  FormControl,
  Validators,
  FormsModule,
  ReactiveFormsModule,
  FormGroup,
  AbstractControl,
} from '@angular/forms';
import { Router, RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { AuthService } from '../authService/auth.service';
import { HttpClientModule } from '@angular/common/http';
import { LoadingSpinnerComponent } from '../../shared/loading-spinner/loading-spinner.component';
import { NotifierService } from '../../shared/notifierService/notifier.service';
import { Subscription, switchMap } from 'rxjs';
import { UserService } from '../../user-profile/user.service';
import {
  hasNumberValidator,
  hasUpperCaseValidator,
} from '../../shared/validation/passwordSaferValidation';
import {
  PasswordValidationType,
  passwordValidator,
} from '../../shared/validation/passwordMatcherValidation';
import { User } from '../model/user.model';
import { MatDialog } from '@angular/material/dialog';
import { CustomDialogComponent } from '../../shared/custom-dialog/custom-dialog.component';
import { HeaderLoginSignupResetpw } from '../../shared/header-login-signup-resetpw/header-lsr.component';
import { PendingActionsService } from '../../score/pending-actions.service';

/**
 * SignUpComponent represents the component responsible for user registration.
 * It allows users to sign up by providing their email, password, and confirming the password.
 * This component utilizes Angular reactive forms for validation and form control management.
 */

@Component({
  selector: 'app-registrierung',
  standalone: true,
  imports: [
    CommonModule,
    AngularMaterialModule,
    FormsModule,
    ReactiveFormsModule,
    RouterModule,
    HttpClientModule,
    LoadingSpinnerComponent,
    HeaderLoginSignupResetpw,
  ],
  providers: [AuthService, UserService],
  templateUrl: './signup-password.component.html',
  styleUrl: './signup-password.component.css',
})
export class SignupPasswordComponent implements OnInit, OnDestroy {
  constructor(
    private authService: AuthService,
    private userService: UserService,
    private notifierService: NotifierService,
    private router: Router,
    private dialog: MatDialog,
    private pendingService: PendingActionsService
  ) {}

  /** Represents the sign-up form group */
  signUpForm!: FormGroup;
  isLoading = false;
  hide = true;
  errorMessagePassword = '';
  errorMessageConfirmPassword = '';

  private passwordValueChangesSubscription!: Subscription;

  ngOnInit() {
    // Initialize the sign-up form with form controls and validators
    this.signUpForm = new FormGroup({
      email: new FormControl('', [
        Validators.required,
        Validators.email,
        Validators.pattern(
          /^[a-zA-Z0-9._%+-]+\.+[a-zA-Z0-9._%+-]+@(eviden\.com|atos\.net)$/
        ),
      ]),
      password: new FormControl('', [
        Validators.required,
        Validators.minLength(10),
        Validators.maxLength(20),
        hasUpperCaseValidator(),
        hasNumberValidator(),
      ]),
      confirmPassword: new FormControl('', [
        Validators.required,
        passwordValidator('password', PasswordValidationType.Match),
      ]),
    });
    // Set up a subscription to the password field's valueChanges observable
    const passwordControl = this.signUpForm.get('password');
    const confirmPasswordControl = this.signUpForm.get('confirmPassword');

    if (passwordControl && confirmPasswordControl) {
      passwordControl.valueChanges.subscribe(() => {
        this.updateErrorMessage();
        confirmPasswordControl.updateValueAndValidity();
      });

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

  //Logs the form data to the console.
  onSubmit() {
    const emailBig = this.signUpForm.get('email')?.value;
    const email = emailBig.toLowerCase();
    const password = this.signUpForm.get('password')?.value;

    // Extract first name and last name from the email address
    const [firstName, lastName] = this.extractNamesFromEmail(email);

    this.isLoading = true;

    this.authService
      .signUpPassword(email, password)
      .pipe(
        switchMap(({ user: { uid } }) => {
          const newUser: User = {
            uid: uid,
            email: email,
            firstName: firstName,
            lastName: lastName,
            firmenposition: null,
            photoUrl: null,
            wins: null,
          };
          this.pendingService.addUserRefToQRCodeData(
            uid,
            this.pendingService.getTempQRId()
          );
          return this.userService.addUser(newUser);
        })
      )
      .subscribe(
        (resData) => {
          this.isLoading = false;
          this.router.navigate(['/score-table']);
          this.dialog.open(CustomDialogComponent, {
            data: {
              title: 'E-Mail-Verifizierung',
              bodyText:
                'Eine Verifizierung-Email wurde an deine Adresse gesendet. Bitte überprüfe dein Postfach und klicke auf den Link, um dein Konto zu verifizieren und Spiele hinzuzufügen.',
            },
          });
        },
        (errorMessage) => {
          this.notifierService.showNotification(errorMessage, 'OK');
          this.isLoading = false;
        }
      );
    this.signUpForm.reset();
  }

  ngOnDestroy() {
    if (this.passwordValueChangesSubscription) {
      this.passwordValueChangesSubscription.unsubscribe();
    }
  }

  private extractNamesFromEmail(email: string): [string, string] {
    const sanitizedEmail = email.replace(/.\d|\.external/g, '');
    const [fullName] = sanitizedEmail.split('@');
    const names = fullName.split('.');

    // Vor- und Nachname grossgeschrieben
    const capitalize = (name: string) =>
      name
        .split('-')
        .map(
          (part) => part.charAt(0).toUpperCase() + part.slice(1).toLowerCase()
        )
        .join('-');

    // Capitalize both the first name and last name parts
    const firstName = names.length > 0 ? capitalize(names[0]) : '';
    const lastName =
      names.length > 1 ? capitalize(names.slice(1).join('-')) : '';

    return [firstName, lastName];
  }

  updateErrorMessage() {
    const passwordControl = this.signUpForm.get('password');
    const confirmPasswordControl = this.signUpForm.get('confirmPassword');

    this.errorMessagePassword = this.getPasswordErrorMessage(passwordControl);
    this.errorMessageConfirmPassword = this.getConfirmPasswordErrorMessage(
      confirmPasswordControl
    );
  }

  private getPasswordErrorMessage(control: AbstractControl | null): string {
    if (control?.hasError('required')) {
      return 'Ein Passwort wird benötigt.';
    } 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 '';
  }
}
