import { Injectable, inject } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { of } from 'rxjs';
import { map, exhaustMap, catchError, withLatestFrom, filter } from 'rxjs/operators';
import { UnitService } from '../../services/unit.service';
import { UnitsActions } from './units.actions';
import { selectUnitsLoaded } from './units.reducer';

@Injectable()
export class UnitsEffects {
  private actions$ = inject(Actions);
  private store = inject(Store);
  private unitService = inject(UnitService);

  loadUnits$ = createEffect(() =>
    this.actions$.pipe(
      ofType(UnitsActions.loadUnits),
      withLatestFrom(this.store.select(selectUnitsLoaded)),
      filter(([action, loaded]) => !loaded || !!action.forceReload),
      exhaustMap(() =>
        this.unitService.listAll().pipe(
          map((response) =>
            UnitsActions.loadUnitsSuccess({
              units: response.data,
              meta: response.meta,
            })
          ),
          catchError((error) =>
            of(UnitsActions.loadUnitsFailure({
              error: error.error?.message || 'Failed to load units',
            }))
          )
        )
      )
    )
  );

  createUnit$ = createEffect(() =>
    this.actions$.pipe(
      ofType(UnitsActions.createUnit),
      exhaustMap(({ unit }) =>
        this.unitService.create(unit).pipe(
          map((response) =>
            UnitsActions.createUnitSuccess({ unit: response.data })
          ),
          catchError((error) =>
            of(UnitsActions.createUnitFailure({
              error: error.error?.message || 'Failed to create unit',
            }))
          )
        )
      )
    )
  );

  updateUnit$ = createEffect(() =>
    this.actions$.pipe(
      ofType(UnitsActions.updateUnit),
      exhaustMap(({ id, unit }) =>
        this.unitService.update(id, unit).pipe(
          map((response) =>
            UnitsActions.updateUnitSuccess({ unit: response.data })
          ),
          catchError((error) =>
            of(UnitsActions.updateUnitFailure({
              error: error.error?.message || 'Failed to update unit',
            }))
          )
        )
      )
    )
  );

  deleteUnit$ = createEffect(() =>
    this.actions$.pipe(
      ofType(UnitsActions.deleteUnit),
      exhaustMap(({ id }) =>
        this.unitService.delete(id).pipe(
          map(() => UnitsActions.deleteUnitSuccess({ id })),
          catchError((error) =>
            of(UnitsActions.deleteUnitFailure({
              error: error.error?.message || 'Failed to delete unit',
            }))
          )
        )
      )
    )
  );
}
