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 { CheckReceivedService } from '../../services/check-received.service';
import { ChecksReceivedActions } from './checks-received.actions';
import { selectChecksReceivedLoaded } from './checks-received.reducer';

@Injectable()
export class ChecksReceivedEffects {
  private actions$ = inject(Actions);
  private store = inject(Store);
  private service = inject(CheckReceivedService);

  load$ = createEffect(() =>
    this.actions$.pipe(
      ofType(ChecksReceivedActions.loadChecksReceived),
      withLatestFrom(this.store.select(selectChecksReceivedLoaded)),
      filter(([action, loaded]) => !loaded || !!action.forceReload),
      exhaustMap(() =>
        this.service.listAll().pipe(
          map((res) => ChecksReceivedActions.loadChecksReceivedSuccess({ checks: res.data, meta: res.meta })),
          catchError((err) => of(ChecksReceivedActions.loadChecksReceivedFailure({ error: err.error?.message || 'Failed to load checks' })))
        )
      )
    )
  );

  create$ = createEffect(() =>
    this.actions$.pipe(
      ofType(ChecksReceivedActions.createCheckReceived),
      exhaustMap(({ check }) =>
        this.service.create(check).pipe(
          map((res) => ChecksReceivedActions.createCheckReceivedSuccess({ check: res.data })),
          catchError((err) => of(ChecksReceivedActions.createCheckReceivedFailure({ error: err.error?.message || 'Failed to create check' })))
        )
      )
    )
  );

  update$ = createEffect(() =>
    this.actions$.pipe(
      ofType(ChecksReceivedActions.updateCheckReceived),
      exhaustMap(({ id, check }) =>
        this.service.update(id, check).pipe(
          map((res) => ChecksReceivedActions.updateCheckReceivedSuccess({ check: res.data })),
          catchError((err) => of(ChecksReceivedActions.updateCheckReceivedFailure({ error: err.error?.message || 'Failed to update check' })))
        )
      )
    )
  );

  delete$ = createEffect(() =>
    this.actions$.pipe(
      ofType(ChecksReceivedActions.deleteCheckReceived),
      exhaustMap(({ id }) =>
        this.service.delete(id).pipe(
          map(() => ChecksReceivedActions.deleteCheckReceivedSuccess({ id })),
          catchError((err) => of(ChecksReceivedActions.deleteCheckReceivedFailure({ error: err.error?.message || 'Failed to delete check' })))
        )
      )
    )
  );

  deposit$ = createEffect(() =>
    this.actions$.pipe(
      ofType(ChecksReceivedActions.depositCheckReceived),
      exhaustMap(({ id, bankAccountId }) =>
        this.service.deposit(id, bankAccountId).pipe(
          map((res) => ChecksReceivedActions.depositCheckReceivedSuccess({ check: res.data })),
          catchError((err) => of(ChecksReceivedActions.depositCheckReceivedFailure({ error: err.error?.message || 'Failed to deposit check' })))
        )
      )
    )
  );

  collect$ = createEffect(() =>
    this.actions$.pipe(
      ofType(ChecksReceivedActions.collectCheckReceived),
      exhaustMap(({ id }) =>
        this.service.collect(id).pipe(
          map((res) => ChecksReceivedActions.collectCheckReceivedSuccess({ check: res.data })),
          catchError((err) => of(ChecksReceivedActions.collectCheckReceivedFailure({ error: err.error?.message || 'Failed to collect check' })))
        )
      )
    )
  );
}
