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 { HrLoanService } from '../../../services/hr-loan.service';
import { HrLoansActions } from './loans.actions';
import { selectHrLoansLoaded } from './loans.reducer';

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

  loadHrLoans$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrLoansActions.loadHRLoans),
      withLatestFrom(this.store.select(selectHrLoansLoaded)),
      filter(([action, loaded]) => !loaded || !!action.forceReload),
      exhaustMap(() =>
        this.service.listAll().pipe(
          map((response) =>
            HrLoansActions.loadHRLoansSuccess({
              loans: response.data,
              meta: response.meta,
            })
          ),
          catchError((error) =>
            of(
              HrLoansActions.loadHRLoansFailure({
                error: error.error?.message || 'Failed to load loans',
              })
            )
          )
        )
      )
    )
  );

  createHrLoan$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrLoansActions.createHRLoan),
      exhaustMap(({ loan }) =>
        this.service.create(loan).pipe(
          map((response) =>
            HrLoansActions.createHRLoanSuccess({ loan: response.data })
          ),
          catchError((error) =>
            of(
              HrLoansActions.createHRLoanFailure({
                error: error.error?.message || 'Failed to create loan',
              })
            )
          )
        )
      )
    )
  );

  updateHrLoan$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrLoansActions.updateHRLoan),
      exhaustMap(({ id, loan }) =>
        this.service.update(id, loan).pipe(
          map((response) =>
            HrLoansActions.updateHRLoanSuccess({ loan: response.data })
          ),
          catchError((error) =>
            of(
              HrLoansActions.updateHRLoanFailure({
                error: error.error?.message || 'Failed to update loan',
              })
            )
          )
        )
      )
    )
  );

  deleteHrLoan$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrLoansActions.deleteHRLoan),
      exhaustMap(({ id }) =>
        this.service.delete(id).pipe(
          map(() => HrLoansActions.deleteHRLoanSuccess({ id })),
          catchError((error) =>
            of(
              HrLoansActions.deleteHRLoanFailure({
                error: error.error?.message || 'Failed to delete loan',
              })
            )
          )
        )
      )
    )
  );

  approveHrLoan$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrLoansActions.approveHRLoan),
      exhaustMap(({ id }) =>
        this.service.approve(id).pipe(
          map((response) =>
            HrLoansActions.approveHRLoanSuccess({ loan: response.data })
          ),
          catchError((error) =>
            of(
              HrLoansActions.approveHRLoanFailure({
                error: error.error?.message || 'Failed to approve loan',
              })
            )
          )
        )
      )
    )
  );

  rejectHrLoan$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrLoansActions.rejectHRLoan),
      exhaustMap(({ id, data }) =>
        this.service.reject(id, data).pipe(
          map((response) =>
            HrLoansActions.rejectHRLoanSuccess({ loan: response.data })
          ),
          catchError((error) =>
            of(
              HrLoansActions.rejectHRLoanFailure({
                error: error.error?.message || 'Failed to reject loan',
              })
            )
          )
        )
      )
    )
  );
}
