import { CommonModule } from '@angular/common';
import { Component, Optional } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { FindActionResDto, FindPrivilegeResDto } from '@api/models';
import { TableColumn } from '@core/models';
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 { DialogModule } from 'primeng/dialog';
import {
  DialogService,
  DynamicDialogConfig,
  DynamicDialogRef,
} from 'primeng/dynamicdialog';
import { IconFieldModule } from 'primeng/iconfield';
import { InputIconModule } from 'primeng/inputicon';
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 { TableModule } from 'primeng/table';
import { TagModule } from 'primeng/tag';
import { ToastModule } from 'primeng/toast';
import { TooltipModule } from 'primeng/tooltip';
import {
  catchError,
  EMPTY,
  endWith,
  map,
  Observable,
  of,
  startWith,
  switchMap,
  tap,
} from 'rxjs';
import { handleDynamicDialog } from '../../../shared/utils/dynamic-dialog-utils';
import { RuoliService } from '../ruoli.service';

export interface ManageRolesDialogComponentState {
  isSaving: boolean;
  isLoading: boolean;
  privileges: FindPrivilegeResDto[];
  availablePrivileges: FindActionResDto[];
  privilegesAreLoading: boolean;
  roleId: number;
  visible: boolean;
  availablePrivilegesAreLoading: boolean;
  selectedAvailablePrivileges: FindActionResDto[];
  settingPrivilegesIsLoading: boolean;
  cdIsLoading: boolean;
}

type State = ManageRolesDialogComponentState;

@Component({
  selector: 'app-manage-roles-dialog',
  imports: [
    CommonModule,
    TableModule,
    InputTextModule,
    SkeletonModule,
    ButtonModule,
    TooltipModule,
    FormsModule,
    ReactiveFormsModule,
    MultiSelectModule,
    ConfirmDialogModule,
    IconFieldModule,
    InputIconModule,
    MessagesModule,
    TagModule,
    ConfirmPopupModule,
    ToastModule,
    InputSwitchModule,
    DialogModule,
    SelectModule,
  ],
  providers: [RxState, DialogService, ConfirmationService],
  templateUrl: './manage-roles-dialog.component.html',
  styleUrl: './manage-roles-dialog.component.scss',
})
export class ManageRolesDialogComponent {
  //state = inject(RxState<State>);

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

  model$: Observable<ManageRolesDialogComponentState>;

  showTransitionOptions = '500ms';

  messages: ToastMessageOptions[] = [];

  livelliPermesso: any[] = [
    {
      value: true,
      label: 'Lettura',
    },
    {
      value: false,
      label: 'Lettura/Scrittura',
    },
  ];

  selectedLevels: any[] = [];

  colsPrivileges: TableColumn[] = [
    { field: 'action.standardCode', header: 'Codice' },
    { field: 'action.description', header: 'Descrizione' },
    { field: 'action.id', header: 'Permessi' },
    { field: 'flagEnabledBoolean', header: 'Abilitazione' },
    { field: 'azioni', header: 'Azioni' },
  ];

  constructor(
    private ruoliService: RuoliService,
    @Optional() readonly dialogRef: DynamicDialogRef,
    @Optional() readonly dialogConfig: DynamicDialogConfig,
    private readonly dialogService: DialogService,
    private confirmationService: ConfirmationService,
    public state: RxState<State>,
  ) {
    this.model$ = this.state.select();

    this.state.set({
      isSaving: false,
      isLoading: false,
      privileges: [],
      availablePrivileges: [],
      privilegesAreLoading: false,
      availablePrivilegesAreLoading: false,
      settingPrivilegesIsLoading: false,
      cdIsLoading: false,
    });

    handleDynamicDialog.bind(this)();

    // handleDynamicDialog.bind({
    //   dialogRef: this.dialogRef,
    //   dialogConfig: this.dialogConfig,
    //   state: this.state,
    // })();
  }

  getPrivileges() {
    const fetchPrivilegiById$ = of(EMPTY).pipe(
      switchMap(() =>
        this.ruoliService.getPrivilegesById(this.state.get('roleId')).pipe(
          catchError(() => of(undefined)),
          tap((res) => {
            if (!res) return;
          }),
          map((res) => ({ privileges: res })),
          startWith({ privilegesAreLoading: true }),
          endWith({ privilegesAreLoading: false }),
        ),
      ),
    );
    this.state.connect(fetchPrivilegiById$);
  }

  onChangeEnableFlag(privilege: FindPrivilegeResDto, value: boolean) {
    const changePrivilegeEnabled$ = this.ruoliService
      .changePrivilegeFlagEnabled(privilege.id, value)
      .pipe(
        catchError((err) => {
          this.messages = [
            {
              severity: 'error',
              summary: 'Attenzione!',
              detail:
                err.status === 400
                  ? err.error.message
                  : 'Impossibile modificare il privilegio in questo momento, riprovare più tardi',
            },
          ];
          return of(null);
        }),
        tap((res) => {
          if (!res) return;
          this.messages = [
            {
              severity: 'success',
              summary: 'Operazione completata!',
              life: 5000,
              detail: 'Privilegio modificato con successo',
            },
          ];
          this.getPrivileges();
        }),
        map(() => ({})),
        startWith({ privilegesAreLoading: true }),
        endWith({ privilegesAreLoading: false }),
      );
    this.state.connect(changePrivilegeEnabled$);
  }

  onChangeLivello(privilegeId: number, value: boolean) {
    const changePrivilegeReadOnlyFlag$ = this.ruoliService
      .changePrivilegeReadOnlyFlag(privilegeId, value)
      .pipe(
        catchError((err) => {
          this.messages = [
            {
              severity: 'error',
              summary: 'Attenzione!',
              detail:
                err.status === 400
                  ? err.error.message
                  : 'Impossibile modificare il privilegio in questo momento, riprovare più tardi',
            },
          ];
          return of(null);
        }),
        tap((res) => {
          if (!res) return;
          this.messages = [
            {
              severity: 'success',
              summary: 'Operazione completata!',
              life: 5000,
              detail: 'Privilegio modificato con successo',
            },
          ];
          this.getPrivileges();
        }),
        map(() => ({})),
        startWith({ privilegesAreLoading: true }),
        endWith({ privilegesAreLoading: false }),
      );
    this.state.connect(changePrivilegeReadOnlyFlag$);
  }

  openAddPrivileges() {
    this.state.set({
      visible: true,
    });
    const fetchPrivilegiById$ = of(EMPTY).pipe(
      switchMap(() =>
        this.ruoliService.getAvailablePrivileges(this.state.get('roleId')).pipe(
          catchError(() => of(null)),
          tap((res) => {
            if (!res) return;
            this.state.set({
              availablePrivileges: res,
            });
          }),
          map(() => ({})),
          startWith({ availablePrivilegesAreLoading: true }),
          endWith({ availablePrivilegesAreLoading: false }),
        ),
      ),
    );
    this.state.connect(fetchPrivilegiById$);
  }

  submitPrivileges() {
    const submitPrivileges$ = of(EMPTY).pipe(
      switchMap(() =>
        this.ruoliService
          .setPrivilegesForRole(
            this.state.get('roleId'),
            this.state.get('selectedAvailablePrivileges'),
          )
          .pipe(
            catchError(() => of(null)),
            tap((res) => {
              if (!res) return;
              this.getPrivileges();
              this.state.set({
                visible: false,
              });
            }),
            map(() => ({})),
            startWith({ settingPrivilegesIsLoading: true }),
            endWith({ settingPrivilegesIsLoading: false }),
          ),
      ),
    );
    this.state.connect(submitPrivileges$);
  }

  onCloseAggiungiPermessiDialog(event: Event) {
    this.state.set({
      selectedAvailablePrivileges: [],
    });
  }

  showDeleteDialog(event: Event, privilegId: number): void {
    this.confirmationService.confirm({
      target: event.target as EventTarget,
      key: 'cd',
      header: 'Elimina privilegio',
      icon: 'pi pi-exclamation-triangle',
      message: 'Sei sicuro di voler eliminare questo privilegio?',
      acceptLabel: 'Sì, elimina',
      acceptButtonStyleClass: 'p-button-rounded',
      rejectButtonStyleClass: 'p-button-rounded p-button-outlined',
      acceptIcon: 'pi pi-trash',
      rejectLabel: 'Annulla',
      accept: () => {
        const saveDeleteChannel$ = this.ruoliService
          .deletePrivilege(privilegId)
          .pipe(
            catchError((err) => of(null)),
            tap((res) => {
              if (!res) return;
              this.messages = [
                {
                  severity: 'success',
                  summary: 'Operazione completata!',
                  life: 5000,
                  detail: 'Privilegio eliminato con successo',
                },
              ];
              this.getPrivileges();
            }),
            map(() => ({})),
            startWith({ cdIsLoading: true }),
            endWith({ cdIsLoading: false }),
          );
        this.state.connect(saveDeleteChannel$);
      },
    });
  }
}
