/* eslint-disable @typescript-eslint/no-unsafe-argument */
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import {
  FormControl,
  FormGroup,
  FormsModule,
  ReactiveFormsModule,
  Validators,
} from '@angular/forms';
import { RouterOutlet } from '@angular/router';
import { RxState } from '@rx-angular/state';
import { ConfirmationService, ToastMessageOptions } from 'primeng/api';
import { ButtonModule } from 'primeng/button';
import { ConfirmDialogModule } from 'primeng/confirmdialog';
import { ConfirmPopupModule } from 'primeng/confirmpopup';
import { DividerModule } from 'primeng/divider';
import { DialogService } from 'primeng/dynamicdialog';
import { IconFieldModule } from 'primeng/iconfield';
import { InputIconModule } from 'primeng/inputicon';
import { InputTextModule } from 'primeng/inputtext';
import { MessagesModule } from 'primeng/messages';
import { MultiSelectModule } from 'primeng/multiselect';
import { PasswordModule } from 'primeng/password';
import { SkeletonModule } from 'primeng/skeleton';
import { TableLazyLoadEvent, TableModule } from 'primeng/table';
import { TagModule } from 'primeng/tag';
import { ToastModule } from 'primeng/toast';
import { TooltipModule } from 'primeng/tooltip';
import { catchError, endWith, map, Observable, of, startWith, tap } from 'rxjs';
import {
  AccountResDto,
  EditAnagraficaPersonaleDto,
  EditPasswordPersonaleDto,
  FindPrivilegeResDto,
  FindProfileResDto,
} from '../../../../api/models';
import { AuthService } from '../../../core/services/auth.service';
import { MustMatch } from '../../../core/validators/password-must-match.validator';
import { RecoveryPasswordService } from '../../recovery-password/recovery-password.service';
import { RuoliService } from './gestisci-profilo.service';

const changePasswordFormGroupFunc = () => ({
  oldPassword: new FormControl<string>('', {
    validators: [Validators.required],
  }),
  newPassword: new FormControl<string>('', {
    nonNullable: true,
    validators: [
      Validators.required,
      Validators.minLength(8),
      Validators.pattern(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*\W).{8,}$/),
    ],
  }),
  confirmPassword: new FormControl<string>('', {
    nonNullable: true,
    validators: [Validators.required],
  }),
});

const changeAnagraficaFormGroupFunc = (profile?: any) => {
  return new FormGroup({
    nome: new FormControl<string | null>(profile?.nome ?? null, {
      validators: [Validators.required],
    }),
    cognome: new FormControl<string | null>(profile?.nome ?? null, {
      validators: [Validators.required],
    }),
  });
};

export type changePasswordForm = FormGroup<
  ReturnType<typeof changePasswordFormGroupFunc>
>;
export type changePasswordFormValue = changePasswordForm['value'];

export type changeAnagraficaForm = ReturnType<
  typeof changeAnagraficaFormGroupFunc
>;
export type changeAnagraficaFormValue = changeAnagraficaForm['value'];

export interface ManageProfileComponentState {
  profiles: FindProfileResDto[];
  profilesAreLoading: boolean;
  profilesTotalCount: number;
  currentFilter?: TableLazyLoadEvent;
  selectedProfile: FindProfileResDto | undefined;
  privileges: FindPrivilegeResDto[];
  profileIsLoading: boolean;
  cdIsLoading: boolean;
  privilegesAreLoading: boolean;
  nome: string | null | undefined;
  cognome: string | null | undefined;
  changePasswordFormSubmitted: boolean;
  changeAnagraficaFormSubmitted: boolean;
  isSaving: boolean;
}
type State = ManageProfileComponentState;

@Component({
  selector: 'app-utenti',
  imports: [
    CommonModule,
    TableModule,
    InputTextModule,
    SkeletonModule,
    ButtonModule,
    TooltipModule,
    FormsModule,
    ReactiveFormsModule,
    MultiSelectModule,
    ConfirmDialogModule,
    IconFieldModule,
    InputIconModule,
    MessagesModule,
    TagModule,
    ConfirmPopupModule,
    ToastModule,
    RouterOutlet,
    PasswordModule,
    DividerModule,
  ],
  providers: [RxState, DialogService, ConfirmationService],
  templateUrl: './gestisci-profilo.component.html',
  styleUrl: './gestisci-profilo.component.scss',
})
export class GestisciProfiloComponent {
  fullName: AccountResDto | null;
  //private state = inject(RxState<State>);

  //model$ = this.state.select();
  showTransitionOptions = '500ms';

  changeAnagraficaForm = changeAnagraficaFormGroupFunc(undefined);

  changePasswordForm = new FormGroup(changePasswordFormGroupFunc(), {
    validators: MustMatch('newPassword', 'confirmPassword'),
  });

  model$: Observable<ManageProfileComponentState>;

  messages: ToastMessageOptions[] = [];

  constructor(
    private ruoliService: RuoliService,
    private readonly dialogService: DialogService,
    private confirmationService: ConfirmationService,
    private authService: AuthService,
    public recoveryService: RecoveryPasswordService,

    private state: RxState<State>,
  ) {
    this.fullName = this.authService.getCurrentUser();

    this.state.set({
      nome: this.fullName?.firstName,
      cognome: this.fullName?.lastName,
    });

    this.model$ = this.state.select();
    this.state.set({
      profiles: [],
      profilesAreLoading: false,
      profilesTotalCount: 0,
      selectedProfile: undefined,
      profileIsLoading: false,
      cdIsLoading: false,
      privilegesAreLoading: false,
      changePasswordFormSubmitted: false,
      isSaving: false,
      changeAnagraficaFormSubmitted: false,
    });

    this.changeAnagraficaForm.patchValue({
      nome: this.state.get('nome'),
      cognome: this.state.get('cognome'),
    });
  }

  submitCambiaPassword() {
    this.state.set({
      changePasswordFormSubmitted: true,
    });
    if (this.changePasswordForm.invalid) return;
    const _changePasswordForm = this.changePasswordForm.getRawValue();
    const params: EditPasswordPersonaleDto = {
      oldPassword: _changePasswordForm.oldPassword!,
      password: _changePasswordForm.newPassword,
    };
    const saveEditPassword$ = this.ruoliService.editPassword(params).pipe(
      catchError((err) => {
        this.messages = [
          {
            severity: 'error',
            summary: 'Errore',
            life: 5000,
            detail:
              err.error.statusCode === 400
                ? err.error.message
                : 'Modifica password non riuscita',
          },
        ];
        return of(null);
      }),

      tap((res) => {
        if (!res) return;
        this.messages = [
          {
            severity: 'success',
            summary: 'Operazione completata',
            life: 5000,
            detail: 'Password modificata con successo',
          },
        ];
        this.state.set(() => ({
          changePasswordFormSubmitted: false,
        }));
      }),
      map(() => ({})),
      startWith({ isSaving: true }),
      endWith({ isSaving: false }),
    );
    this.state.connect(saveEditPassword$);
  }

  submitCambiaAnagrafica() {
    this.state.set({
      changeAnagraficaFormSubmitted: true,
    });
    if (this.changeAnagraficaForm.invalid) return;
    const _changeAnagraficaForm = this.changeAnagraficaForm.getRawValue();
    const params: EditAnagraficaPersonaleDto = {
      nome: _changeAnagraficaForm.nome!,
      cognome: _changeAnagraficaForm.cognome!,
    };
    const saveEditAnagrafica$ = this.ruoliService.editAnagrafica(params).pipe(
      catchError((err) => {
        this.messages = [
          {
            severity: 'error',
            summary: 'Errore',
            life: 5000,
            detail: 'Modifica anagrafica non riuscita',
          },
        ];
        return of(null);
      }),
      tap((res) => {
        if (!res) return;
        this.messages = [
          {
            severity: 'success',
            summary: 'Operazione completata',
            life: 5000,
            detail: 'Anagrafica modificata con successo',
          },
        ];
        this.authService.getCurrentUser();
        this.state.set(() => ({
          changeAnagraficaFormSubmitted: false,
        }));
      }),
      map(() => ({})),
      startWith({ isSaving: true }),
      endWith({ isSaving: false }),
    );
    this.state.connect(saveEditAnagrafica$);
  }
}
