import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { Store } from '@ngrx/store';

import { ApiFitService } from 'src/app/shared/services/api-fit/api-fit.service';

import { SignupStore } from 'src/app/core/interfaces/store/signup.store';

import { SignupDispatchers } from 'src/app/core/stores/index.dispatchers';
import { AuthService } from 'src/app/core/services/auth/auth.service';
import { USER_REGEX } from 'src/app/shared/constants/regex.constants';

type FormData = Pick<
  SignupStore,
  'fullName' | 'email' | 'username' | 'password'
>;

@Component({
  selector: 'app-user',
  templateUrl: './user.component.html',
  styleUrls: ['./user.component.scss'],
})
export class UserComponent {
  user: SignupStore = {
    fullName: '',
    username: '',
    email: '',
    password: '',
    gender: 'male',
    birthDate: new Date(),
    height: 0,
    weight: 0,
    goalId: 0,
    physicalActivityId: 0,
  };

  errorsList: Record<
    keyof FormData | 'repeatedPassword',
    {
      actual: string;
      regexError: string;
    }
  > = {
    fullName: {
      actual: '',
      regexError: 'Por favor, digite seu nome completo',
    },
    username: {
      actual: '',
      regexError: 'O nome de usuário deve conter apenas letras, números e/ou _',
    },
    email: {
      actual: '',
      regexError: 'Por favor, digite um e-mail válido',
    },
    password: {
      actual: '',
      regexError: 'A senha deve conter no mínimo 8 caracteres',
    },
    repeatedPassword: {
      actual: '',
      regexError: 'A senha deve conter no mínimo 8 caracteres',
    },
  };

  regexList = {
    name: USER_REGEX.fullName,
    username: USER_REGEX.username,
    email: USER_REGEX.email,
    password: USER_REGEX.password,
  };

  repeatedPassword = '';

  constructor(
    private apiFitService: ApiFitService,
    private store: Store<{ signup: SignupStore }>,
    private authService: AuthService,
    private signupDispatchers: SignupDispatchers,
    private router: Router,
  ) {
    this.store.select('signup').subscribe({
      next: (data) => {
        Object.assign(this.user, data);
      },
    });
  }

  ngOnInit() {
    const token = this.authService.getAuthorizationToken();

    if (token) {
      this.router.navigate(['/app/home']);
      return;
    }
  }

  isSocialSignup() {
    return this.user.googleToken;
  }

  checkUsernameDisponibility(username: string) {
    if (this.errorsList['username'].actual) return;

    if (!username) {
      this.showMessageError('username', '');
      return;
    }

    this.apiFitService.checkUsernameExists({ username }).subscribe({
      next: () => {
        this.showMessageError('username', 'Este nome de usuário já existe');
      },
      error: () => this.showMessageError('username', ''),
    });
  }

  checkEmailDisponibility(email: string) {
    if (this.errorsList['email'].actual) return;

    if (!email) {
      this.showMessageError('email', '');
      return;
    }

    this.apiFitService.checkEmailExists({ email }).subscribe({
      next: () => {
        this.showMessageError('email', 'Este e-mail já está cadastrado');
      },
      error: () => this.showMessageError('email', ''),
    });
  }

  verifyPasswordMatch() {
    if (!this.user.password.trim() || !this.repeatedPassword.trim())
      return false;

    if (this.user.password !== this.repeatedPassword) {
      this.showMessageError('repeatedPassword', 'As senhas não coincidem');
    } else {
      this.showMessageError('repeatedPassword', '');
    }

    return this.user.password === this.repeatedPassword;
  }

  showMessageError(
    field: keyof FormData | 'repeatedPassword',
    message: string,
  ) {
    this.errorsList[field].actual = message;
  }

  isFormValid() {
    if (Object.values(this.errorsList).some((error) => error.actual))
      return false;

    if (this.isSocialSignup()) {
      return this.user.fullName.trim() && this.user.username.trim();
    }

    const form: FormData = {
      fullName: this.user.fullName,
      email: this.user.email,
      username: this.user.username,
      password: this.user.password,
    };

    return Object.values(form).every((d) => d) && this.verifyPasswordMatch();
  }

  validateUsername(username: string) {
    const isNumber = (value: string) => !isNaN(parseFloat(value));
    const errorList = this.errorsList['username'];

    const illegalCombinations = ['..', '__', '._', '_.'];

    if (isNumber(username[0])) {
      errorList.actual = 'O nome de usuário deve começar com uma letra';
      return;
    }

    if (illegalCombinations.some(combination => username.includes(combination))) {
      errorList.actual = 'O nome de usuário não deve conter múltiplos pontos/underlines seguidos';
      return;
    }

    if (username.length > 32) {
      errorList.actual = 'O nome de usuário deve ser menor que 32 caracteres';
      return;
    }
  }

  continueSignup() {
    this.signupDispatchers.setSignup({
      ...this.user,
      fullName: this.user.fullName.trim(),
      username: this.user.username.trim(),
      email: this.user.email.trim(),
      password: this.user.password.trim(),
    });

    this.router.navigate(['/app/auth/signup/person']);
  }
}
