import { Component, DestroyRef, inject, OnInit, OnDestroy } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import {
    UntypedFormBuilder,
    UntypedFormGroup,
    AbstractControl,
    Validators,
    ValidatorFn,
    ValidationErrors,
    FormsModule,
    ReactiveFormsModule,
} from '@angular/forms';
import { Title } from '@angular/platform-browser';
import { ActivatedRoute, Router, RouterLink } from '@angular/router';
import { MatButtonModule } from '@angular/material/button';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';

import { Subscription } from 'rxjs';
import { take } from 'rxjs/operators';

import { Errors } from '@models';
import { UserService } from '@services';
import { ListErrorsComponent } from '@components/shared';

@Component({
    imports: [
        RouterLink,
        FormsModule,
        ReactiveFormsModule,
        MatFormFieldModule,
        MatInputModule,
        MatButtonModule,
        ListErrorsComponent,
    ],
    selector: 'app-auth',
    templateUrl: './auth.component.html',
    styleUrl: './auth.component.scss',
})
export class AuthComponent implements OnInit, OnDestroy {
    private route = inject(ActivatedRoute);
    private router = inject(Router);
    private titleService = inject(Title);
    private userService = inject(UserService);
    private fb = inject(UntypedFormBuilder);

    private _url: Subscription = new Subscription();
    private _user: Subscription = new Subscription();
    authType = '';
    title = '';
    btnTitle = '';
    errors: Errors = { errors: {} };
    isSubmitting = false;
    authForm!: UntypedFormGroup;
    destroyRef = inject(DestroyRef);

    constructor() {
        this._resetErrors();
        // use FormBuilder to create a form group
        const controlsConfig = {
            email: ['', [Validators.required, Validators.email]],
            username: '',
            firstname: '',
            lastname: '',
            phone: '',
            licence: '',
            poids: '',
            password: ['', Validators.required],
            confirmPassword: '',
        };
        this.authForm = this.fb.group(controlsConfig, { validators: this.checkPasswords });
    }

    ngOnInit() {
        // you would normally unsubscribe from this observable subscription
        // the active route observables are exemptions from unsubribe always rule
        // see notes on: https://angular.io/guide/router#observable-parammap-and-component-reuse
        this.route.url.pipe(take(1)).subscribe((data) => {
            // Get the last piece of the URL (it's either 'login' or 'register')
            this.authType = data[data.length - 1].path;
            // Set a title for the page accordingly
            if (this.authType === 'register') {
                this.title = 'Création de compte';
                this.btnTitle = 'Créer le compte';
                this.titleService.setTitle(`Ad Astra - Créer un compte`);
            } else {
                this.title = 'Se connecter';
                this.btnTitle = 'Se connecter';
                this.titleService.setTitle(`Ad Astra - Connexion`);
            }
            // add form control for username if this is the register page
            if (this.authType === 'register') {
                this.authForm.controls['firstname'].setValidators([Validators.required]);
                this.authForm.controls['lastname'].setValidators([Validators.required]);
                this.authForm.controls['phone'].setValidators([Validators.required]);
                this.authForm.controls['confirmPassword'].setValidators([Validators.minLength(8), Validators.required]);
            }
        });
    }

    ngOnDestroy() {
        this._user.unsubscribe();
        //this._url.unsubscribe();
    }

    submitForm() {
        this.isSubmitting = true;
        this.errors = { errors: {} };

        if (this.authForm.valid) {
            this._resetErrors();
            const credentials = this.authForm.value;
            const user$ = this.userService
                .attemptAuth(this.authType, credentials)
                .pipe(takeUntilDestroyed(this.destroyRef));
            this._user = user$.subscribe({
                next: () => void this.router.navigateByUrl('/'),
                error: (err) => {
                    console.log(err);
                    this.errors = err;
                    this.isSubmitting = false;
                },
            });
        }
    }

    getErrorMessage(name: string) {
        switch (name) {
            case 'email':
                if (this.authForm.controls['email'].errors !== null) {
                    return 'Indiquez votre adresse email';
                }
                break;
            case 'firstname':
                if (this.authForm.controls['firstname'].errors !== null) {
                    return 'Vous devez indiquer votre prénnom';
                }
                break;
            case 'lastname':
                if (this.authForm.controls['lastname'].errors !== null) {
                    return 'Vous devez indiquer votre nom';
                }
                break;
            case 'phone':
                if (this.authForm.controls['phone'].errors !== null) {
                    return 'Vous devez indiquer votre numéro de téléphone';
                }
                break;
            case 'password':
                if (this.authForm.controls['password'].errors !== null) {
                    return 'Un mot de passe est obligatoire';
                }
                break;
            case 'confirmPassword':
                if (this.authForm.controls['confirmPassword'].errors !== null) {
                    return 'Une confirmation du mot de passe est obligatoire';
                }
                break;
        }
        return '';
    }

    checkPasswords: ValidatorFn = (group: AbstractControl): ValidationErrors | null => {
        if (this.authType !== 'register') {
            return null;
        }
        const pass = group.get('password')!.value;
        const confirmPass = group.get('confirmPassword')!.value;
        return pass === confirmPass && pass !== '' ? null : { notSame: true };
    };

    private _resetErrors(): void {
        this.errors = { errors: {} };
    }
}
