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 { HrPayrollService } from '../../../services/hr-payroll.service';
import { HrPayrollActions } from './payroll.actions';
import { selectHrPayrollLoaded } from './payroll.reducer';

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

  loadHrPayroll$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrPayrollActions.loadHRPayroll),
      withLatestFrom(this.store.select(selectHrPayrollLoaded)),
      filter(([action, loaded]) => !loaded || !!action.forceReload),
      exhaustMap(() =>
        this.service.listAll().pipe(
          map((response) =>
            HrPayrollActions.loadHRPayrollSuccess({
              payrolls: response.data,
              meta: response.meta,
            })
          ),
          catchError((error) =>
            of(
              HrPayrollActions.loadHRPayrollFailure({
                error: error.error?.message || 'Failed to load payroll',
              })
            )
          )
        )
      )
    )
  );

  createHrPayroll$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrPayrollActions.createHRPayroll),
      exhaustMap(({ payroll }) =>
        this.service.create(payroll).pipe(
          map((response) =>
            HrPayrollActions.createHRPayrollSuccess({ payroll: response.data })
          ),
          catchError((error) =>
            of(
              HrPayrollActions.createHRPayrollFailure({
                error: error.error?.message || 'Failed to create payroll',
              })
            )
          )
        )
      )
    )
  );

  updateHrPayroll$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrPayrollActions.updateHRPayroll),
      exhaustMap(({ id, payroll }) =>
        this.service.update(id, payroll).pipe(
          map((response) =>
            HrPayrollActions.updateHRPayrollSuccess({ payroll: response.data })
          ),
          catchError((error) =>
            of(
              HrPayrollActions.updateHRPayrollFailure({
                error: error.error?.message || 'Failed to update payroll',
              })
            )
          )
        )
      )
    )
  );

  deleteHrPayroll$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrPayrollActions.deleteHRPayroll),
      exhaustMap(({ id }) =>
        this.service.delete(id).pipe(
          map(() => HrPayrollActions.deleteHRPayrollSuccess({ id })),
          catchError((error) =>
            of(
              HrPayrollActions.deleteHRPayrollFailure({
                error: error.error?.message || 'Failed to delete payroll',
              })
            )
          )
        )
      )
    )
  );

  calculateHrPayroll$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrPayrollActions.calculateHRPayroll),
      exhaustMap(({ id }) =>
        this.service.calculate(id).pipe(
          map((response) =>
            HrPayrollActions.calculateHRPayrollSuccess({ payroll: response.data })
          ),
          catchError((error) =>
            of(
              HrPayrollActions.calculateHRPayrollFailure({
                error: error.error?.message || 'Failed to calculate payroll',
              })
            )
          )
        )
      )
    )
  );

  approveHrPayroll$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrPayrollActions.approveHRPayroll),
      exhaustMap(({ id }) =>
        this.service.approve(id).pipe(
          map((response) =>
            HrPayrollActions.approveHRPayrollSuccess({ payroll: response.data })
          ),
          catchError((error) =>
            of(
              HrPayrollActions.approveHRPayrollFailure({
                error: error.error?.message || 'Failed to approve payroll',
              })
            )
          )
        )
      )
    )
  );

  postHrPayroll$ = createEffect(() =>
    this.actions$.pipe(
      ofType(HrPayrollActions.postHRPayroll),
      exhaustMap(({ id }) =>
        this.service.post(id).pipe(
          map((response) =>
            HrPayrollActions.postHRPayrollSuccess({ payroll: response.data })
          ),
          catchError((error) =>
            of(
              HrPayrollActions.postHRPayrollFailure({
                error: error.error?.message || 'Failed to post payroll',
              })
            )
          )
        )
      )
    )
  );
}
