import { CommonModule } from '@angular/common';
import { Component, Optional } from '@angular/core';
import {
  FormControl,
  FormGroup,
  FormsModule,
  ReactiveFormsModule,
  Validators,
} from '@angular/forms';
import { FindAccountResDto, FindRoleResDto } from '@api/models';
import { RxState } from '@rx-angular/state';
import dayjs from 'dayjs';
import { ToastMessageOptions } from 'primeng/api';
import { ButtonModule } from 'primeng/button';
import { CalendarModule } from 'primeng/calendar';
import { DatePickerModule } from 'primeng/datepicker';
import { DividerModule } from 'primeng/divider';
import { DropdownModule } from 'primeng/dropdown';
import {
  DialogService,
  DynamicDialogConfig,
  DynamicDialogRef,
} from 'primeng/dynamicdialog';
import { InputSwitchModule } from 'primeng/inputswitch';
import { InputTextModule } from 'primeng/inputtext';
import { MessagesModule } from 'primeng/messages';
import { MultiSelectModule } from 'primeng/multiselect';
import { SelectModule } from 'primeng/select';
import { SkeletonModule } from 'primeng/skeleton';
import { combineLatest, EMPTY, Observable, of } from 'rxjs';
import {
  catchError,
  endWith,
  map,
  startWith,
  switchMap,
  tap,
} from 'rxjs/operators';
import { handleDynamicDialog } from '../../../shared/utils/dynamic-dialog-utils';
import { UtentiService } from '../utenti.service';

const userFormGroupFunc = (user?: FindAccountResDto) => ({
  firstName: new FormControl<string | null>(user?.firstName ?? null, {
    validators: [Validators.required],
  }),
  lastName: new FormControl<string | null>(user?.lastName ?? null, {
    validators: [Validators.required],
  }),
  username: new FormControl<string | null>(user?.username ?? null, {
    validators: [Validators.required, Validators.email],
  }),
  expireDate: new FormControl<Date | null>(
    user?.expireDate &&
    dayjs(user.expireDate)
      .startOf('day')
      .isBefore(dayjs('9998-12-31').startOf('day'))
      ? new Date(user?.expireDate)
      : null,
  ),
  // statusID: new FormControl<number | null>(user?.statusID ?? null, {
  //     validators: [Validators.required],
  //   }),
  ruolo: new FormControl<number | null>(user?.profiles[0].role.id ?? null, {
    validators: [Validators.required],
  }),
});
export type UserForm = FormGroup<ReturnType<typeof userFormGroupFunc>>;
export type AccountFormValue = UserForm['value'];

export interface ManageUsersDialogComponentState {
  isSaving: boolean;
  isLoading: boolean;
  userFormSubmitted: boolean;
  selectedUser: FindAccountResDto;
  ruoli: FindRoleResDto[];
  ruoliIsLoading: boolean;
  user: FindAccountResDto;
}

type State = ManageUsersDialogComponentState;

@Component({
  imports: [
    CommonModule,
    SkeletonModule,
    InputSwitchModule,
    FormsModule,
    ButtonModule,
    DividerModule,
    DropdownModule,
    ReactiveFormsModule,
    InputTextModule,
    CalendarModule,
    MultiSelectModule,
    SelectModule,
    DatePickerModule,
    MessagesModule,
  ],
  providers: [RxState, DialogService],
  selector: 'manage-users-dialog',
  templateUrl: 'manage-users-dialog.component.html',
  styleUrl: './manage-users-dialog.component.scss',
})
export class ManageUsersDialogComponent {
  //state = inject(RxState<State>);

  //model$ = this.state.select();

  model$: Observable<ManageUsersDialogComponentState>;

  userForm = new FormGroup(userFormGroupFunc(undefined));

  showTransitionOptions = '500ms';

  messages: ToastMessageOptions[] = [];

  constructor(
    @Optional() readonly dialogRef: DynamicDialogRef,
    @Optional() readonly dialogConfig: DynamicDialogConfig,
    private utentiService: UtentiService,
    public state: RxState<State>,
  ) {
    this.model$ = this.state.select();

    this.state.set({
      isSaving: false,
      isLoading: false,
      userFormSubmitted: false,
    });

    handleDynamicDialog.bind(this)();

    // const patchForm$ = combineLatest([
    //   this.state.select('ruoli'),
    //   this.state.select('selectedUser'),
    // ]).pipe(
    //   switchMap(([ruoli, user]) => {
    //     return of(user).pipe(
    //       tap(() => {
    //         this.userForm.patchValue(
    //           new FormGroup(userFormGroupFunc(user)).value,
    //         );
    //       }),
    //       startWith({ isLoading: true }),
    //       endWith({ isLoading: false }),
    //     );
    //   }),
    // );
    // this.state.connect(patchForm$);

    const patchForm$ = combineLatest([
      this.state.select('ruoli'),
      this.state.select('selectedUser'),
    ]).pipe(
      switchMap(([ruoli, user]) => {
        return of(user).pipe(
          tap(() => {
            this.userForm.patchValue(
              new FormGroup(userFormGroupFunc(user)).value,
            );
          }),
          map((user) => ({ user })),
          startWith({ isLoading: true }),
          endWith({ isLoading: false }),
        );
      }),
    );

    this.state.connect(patchForm$);

    const fetchRuoli$ = of(EMPTY).pipe(
      switchMap(() =>
        this.utentiService.getRoles().pipe(
          map((res) => ({
            ruoli: res,
          })),
          startWith({ ruoliIsLoading: true }),
          endWith({ ruoliIsLoading: false }),
        ),
      ),
    );
    this.state.connect(fetchRuoli$);
  }

  submitUserForm() {
    this.state.set({
      userFormSubmitted: true,
    });
    if (this.userForm.invalid) return;
    const _userForm = this.userForm.getRawValue();
    const params = {
      username: _userForm.username ?? 'null',
      firstName: _userForm.firstName ?? 'null',
      lastName: _userForm.lastName ?? 'null',
      roleId: _userForm.ruolo ?? 0,
      ...(this.state.get('selectedUser') && {
        expireDate: _userForm.expireDate
          ? _userForm.expireDate.toISOString()
          : null,
      }),
      ...(this.state.get('selectedUser') && {
        profileId: this.state.get('selectedUser').profiles[0].id,
      }),
    };
    const saveAddUser$ = (
      !this.state.get('selectedUser')
        ? this.utentiService.createUser(params)
        : this.utentiService.editUser(this.state.get('selectedUser').id, params)
    ).pipe(
      catchError((err) => {
        this.messages = [
          {
            severity: 'error',
            summary: 'Attenzione!',
            detail:
              err.status === 400
                ? err.error.message
                : "Impossibile creare l'account in questo momento, riprovare più tardi",
          },
        ];
        return of(null);
      }),
      tap((res) => {
        if (!res) return;
        this.state.set(() => ({
          userFormSubmitted: false,
        }));
        this.dialogRef.close('success');
      }),
      map(() => ({})),
      startWith({ isSaving: true }),
      endWith({ isSaving: false }),
    );
    this.state.connect(saveAddUser$);
  }

  cancelForm() {
    this.dialogRef?.close();
  }
}
