import { CommonModule } from '@angular/common';
import { Component, Optional } from '@angular/core';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { Stipulatore, Struttura } from '@api/models';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
import { RxState } from '@rx-angular/state';
import { ToastMessageOptions } from 'primeng/api';
import { AutoCompleteModule } from 'primeng/autocomplete';
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 { RatingModule } from 'primeng/rating';
import { SelectModule } from 'primeng/select';
import { SkeletonModule } from 'primeng/skeleton';
import { TableModule } from 'primeng/table';
import { TextareaModule } from 'primeng/textarea';
import { ToggleSwitch } from 'primeng/toggleswitch';
import { EMPTY, Observable, of, Subject } from 'rxjs';
import {
  catchError,
  endWith,
  map,
  startWith,
  switchMap,
  tap,
} from 'rxjs/operators';
import { handleDynamicDialog } from '../../../shared/utils/dynamic-dialog-utils';
import { StruttureService } from '../strutture.service';

export interface StipulatoreConFlag extends Stipulatore {
  flagProprietario: boolean;
}
export interface GestioneVisibilitaDialogComponentState {
  isSaving: boolean;
  isLoading: boolean;
  selectedStruttura: Struttura;
  stipulatoriAreLoading: boolean;
  stipulatori: Stipulatore[];
  selectedStipulatori: StipulatoreConFlag[];
}

type State = GestioneVisibilitaDialogComponentState;

@Component({
  imports: [
    CommonModule,
    SkeletonModule,
    InputSwitchModule,
    FormsModule,
    ButtonModule,
    DividerModule,
    DropdownModule,
    ReactiveFormsModule,
    InputTextModule,
    CalendarModule,
    MultiSelectModule,
    SelectModule,
    DatePickerModule,
    MessagesModule,
    AutoCompleteModule,
    FontAwesomeModule,
    RatingModule,
    TextareaModule,
    TableModule,
    ToggleSwitch,
  ],
  providers: [RxState, DialogService],
  selector: 'manage-visibilita-dialog',
  templateUrl: 'manage-visibilita-dialog.component.html',
  styleUrl: './manage-visibilita-dialog.component.scss',
})
export class GestioneVisibilitaDialogComponent {
  model$: Observable<GestioneVisibilitaDialogComponentState>;

  showTransitionOptions = '500ms';

  messages: ToastMessageOptions[] = [];

  setValueEvent: Subject<string | null> = new Subject<string | null>();
  private destroy$ = new Subject<void>();

  constructor(
    @Optional() readonly dialogRef: DynamicDialogRef,
    @Optional() readonly dialogConfig: DynamicDialogConfig,
    private struttureService: StruttureService,
    public state: RxState<State>,
  ) {
    this.model$ = this.state.select();
    this.state.set({
      isSaving: false,
      isLoading: false,
      stipulatori: [],
      stipulatoriAreLoading: false,
    });

    const fetchStipulatori$ = of(EMPTY).pipe(
      switchMap(() =>
        this.struttureService.getAllStipulatori().pipe(
          map((res) => {
            const struttura = this.state.get()?.selectedStruttura;
            const visibilita = struttura?.visibilitaStrutture ?? [];

            const stipulatoriConFlag = res.rows.map((stip) => {
              const match = visibilita.find((v) => v.idStipulatore === stip.id);
              return {
                ...stip,
                flagProprietario: match?.flagProprietario ?? false,
              };
            });

            const selectedStipulatori = stipulatoriConFlag.filter((stip) =>
              visibilita.some((v) => v.idStipulatore === stip.id),
            );

            return {
              stipulatori: stipulatoriConFlag,
              selectedStipulatori,
            };
          }),
          catchError(() => of({ stipulatori: [], selectedStipulatori: [] })),
          startWith({ stipulatoriAreLoading: true }),
          endWith({ stipulatoriAreLoading: false }),
        ),
      ),
    );

    this.state.connect(fetchStipulatori$);

    handleDynamicDialog.bind(this)();
  }

  isStipulatoreSelezionato(stipulatoreId: number): boolean {
    const selected = this.state.get('selectedStipulatori') ?? [];
    return selected.some((s) => s.id === stipulatoreId);
  }

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

  submitStruttureForm() {
    const strutturaId = this.state.get('selectedStruttura')?.id;
    if (!strutturaId) return;

    const selectedStipulatori = this.state.get('selectedStipulatori') ?? [];

    const visibilitaStrutture = selectedStipulatori.map((stip) => ({
      idStipulatore: stip.id,
      flagProprietario: stip.flagProprietario ?? false,
    }));

    const body = { visibilitaStrutture };

    const editVisibilitaStrutture$ = this.struttureService
      .editVisibilita(strutturaId, body)
      .pipe(
        catchError(() => of(null)),
        tap((res) => {
          if (!res) return;
          this.dialogRef.close(res);
        }),
        map(() => ({})),
        startWith({ isSaving: true }),
        endWith({ isSaving: false }),
      );

    this.state.connect(editVisibilitaStrutture$);
  }

  ngOnDestroy() {
    this.destroy$.next();
    this.destroy$.complete();
  }
}
