import { ChangeDetectionStrategy, Component, inject, signal } from '@angular/core';
import { FormBuilder, ReactiveFormsModule, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';

import { AuthService } from '../../../../core/services/auth/auth.service';
import { ToastService } from '../../../../core/services/toast.service';
import { ButtonComponent } from '../../../../shared/components/button/button.component';
import { InputComponent } from '../../../../shared/components/input/input.component';

const EMAIL_MAX_LENGTH = 255;

@Component({
  selector: 'app-recover-password-page',
  imports: [ReactiveFormsModule, InputComponent, ButtonComponent],
  templateUrl: './recover-password-page.component.html',
  styleUrl: './recover-password-page.component.scss',
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class RecoverPasswordPageComponent {
  private readonly formBuilder = inject(FormBuilder);
  private readonly router = inject(Router);
  private readonly route = inject(ActivatedRoute);
  private readonly authService = inject(AuthService);
  private readonly toastService = inject(ToastService);
  private readonly submittedState = signal(false);
  private readonly isSubmittingState = signal(false);
  private readonly serverErrorState = signal<string | null>(null);

  protected readonly form = this.formBuilder.nonNullable.group({
    email: [
      this.route.snapshot.queryParamMap.get('email') ?? '',
      [Validators.required, Validators.email, Validators.maxLength(EMAIL_MAX_LENGTH)],
    ],
  });
  protected readonly submitted = this.submittedState.asReadonly();
  protected readonly isSubmitting = this.isSubmittingState.asReadonly();
  protected readonly serverError = this.serverErrorState.asReadonly();

  protected updateEmail(value: string | number): void {
    this.form.controls.email.setValue(String(value));
  }

  protected showEmailError(): boolean {
    const email = this.form.controls.email;

    return email.invalid && (email.touched || this.submitted());
  }

  protected getEmailError(): string | null {
    const email = this.form.controls.email;

    if (!this.showEmailError()) {
      return null;
    }

    if (email.hasError('required')) {
      return 'Este campo es obligatorio.';
    }

    if (email.hasError('maxlength')) {
      return `No puede superar los ${EMAIL_MAX_LENGTH} caracteres.`;
    }

    if (email.hasError('email')) {
      return 'Ingresa un email válido.';
    }

    return 'El valor ingresado no es válido.';
  }

  protected onSubmit(): void {
    this.submittedState.set(true);
    this.serverErrorState.set(null);

    if (this.form.invalid || this.isSubmitting()) {
      this.form.markAllAsTouched();
      return;
    }

    const email = this.form.controls.email.value;
    this.isSubmittingState.set(true);

    this.authService.requestPasswordReset(email).subscribe({
      next: (response) => {
        this.isSubmittingState.set(false);

        if (response.status !== 202 || response.body?.status !== 'pending') {
          console.warn('Password reset attempt returned an unexpected status.', {
            httpStatus: response.status,
            attemptStatus: response.body?.status ?? null,
          });
          this.showServerError('No se pudo iniciar la recuperación. Intenta nuevamente.');
          return;
        }

        void this.router.navigate(['/recuperar-contrasena/codigo'], {
          queryParams: { email },
        });
      },
      error: (error: unknown) => {
        this.isSubmittingState.set(false);
        console.error('Password reset attempt request failed.', error);
        this.showServerError(this.resolveErrorMessage(error));
      },
    });
  }

  protected goToLogin(): void {
    void this.router.navigate(['/login']);
  }

  private showServerError(message: string): void {
    this.serverErrorState.set(message);
    this.toastService.danger(message);
  }

  private resolveErrorMessage(error: unknown): string {
    const errorPayload =
      typeof error === 'object' && error !== null && 'error' in error
        ? (error as { error?: { errors?: Record<string, string[]>; message?: string } }).error
        : undefined;
    const emailMessages = errorPayload?.errors?.['email'];
    const emailError = Array.isArray(emailMessages) ? emailMessages[0] : null;

    if (typeof emailError === 'string' && emailError.trim()) {
      return emailError;
    }

    if (typeof errorPayload?.message === 'string' && errorPayload.message.trim()) {
      return errorPayload.message;
    }

    return 'No se pudo iniciar la recuperación. Intenta nuevamente.';
  }
}
