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 { SalesReturnService } from '../../../services/sales-return.service';
import { SalesReturnsActions } from './returns.actions';
import { selectSalesReturnsLoaded } from './returns.reducer';

@Injectable()
export class SalesReturnsEffects {
  private actions$ = inject(Actions);
  private store = inject(Store);
  private returnService = inject(SalesReturnService);

  loadReturns$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesReturnsActions.loadReturns),
      withLatestFrom(this.store.select(selectSalesReturnsLoaded)),
      filter(([action, loaded]) => !!action.force || !loaded),
      exhaustMap(() =>
        this.returnService.listAll().pipe(
          map((response) =>
            SalesReturnsActions.loadReturnsSuccess({
              returns: response.data,
              meta: response.meta,
            })
          ),
          catchError((error) =>
            of(
              SalesReturnsActions.loadReturnsFailure({
                error: error.error?.message || 'Failed to load returns',
              })
            )
          )
        )
      )
    )
  );

  createReturn$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesReturnsActions.createReturn),
      exhaustMap(({ data }) =>
        this.returnService.create(data).pipe(
          map((response) =>
            SalesReturnsActions.createReturnSuccess({ salesReturn: response.data })
          ),
          catchError((error) =>
            of(
              SalesReturnsActions.createReturnFailure({
                error: error.error?.message || 'Failed to create return',
              })
            )
          )
        )
      )
    )
  );

  updateReturn$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesReturnsActions.updateReturn),
      exhaustMap(({ id, data }) =>
        this.returnService.update(id, data).pipe(
          map((response) =>
            SalesReturnsActions.updateReturnSuccess({ salesReturn: response.data })
          ),
          catchError((error) =>
            of(
              SalesReturnsActions.updateReturnFailure({
                error: error.error?.message || 'Failed to update return',
              })
            )
          )
        )
      )
    )
  );

  deleteReturn$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesReturnsActions.deleteReturn),
      exhaustMap(({ id }) =>
        this.returnService.delete(id).pipe(
          map(() => SalesReturnsActions.deleteReturnSuccess({ id })),
          catchError((error) =>
            of(
              SalesReturnsActions.deleteReturnFailure({
                error: error.error?.message || 'Failed to delete return',
              })
            )
          )
        )
      )
    )
  );

  submitReturnApproval$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesReturnsActions.submitReturnApproval),
      exhaustMap(({ id }) =>
        this.returnService.submitApproval(id).pipe(
          map((response) =>
            SalesReturnsActions.submitReturnApprovalSuccess({ salesReturn: response.data })
          ),
          catchError((error) =>
            of(
              SalesReturnsActions.submitReturnApprovalFailure({
                error: error.error?.message || 'Failed to submit return for approval',
              })
            )
          )
        )
      )
    )
  );

  approveReturn$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesReturnsActions.approveReturn),
      exhaustMap(({ id }) =>
        this.returnService.approve(id).pipe(
          map((response) =>
            SalesReturnsActions.approveReturnSuccess({ salesReturn: response.data })
          ),
          catchError((error) =>
            of(
              SalesReturnsActions.approveReturnFailure({
                error: error.error?.message || 'Failed to approve return',
              })
            )
          )
        )
      )
    )
  );

  rejectReturn$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesReturnsActions.rejectReturn),
      exhaustMap(({ id }) =>
        this.returnService.reject(id).pipe(
          map((response) =>
            SalesReturnsActions.rejectReturnSuccess({ salesReturn: response.data })
          ),
          catchError((error) =>
            of(
              SalesReturnsActions.rejectReturnFailure({
                error: error.error?.message || 'Failed to reject return',
              })
            )
          )
        )
      )
    )
  );

  postReturn$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesReturnsActions.postReturn),
      exhaustMap(({ id }) =>
        this.returnService.post(id).pipe(
          map((response) =>
            SalesReturnsActions.postReturnSuccess({ salesReturn: response.data })
          ),
          catchError((error) =>
            of(
              SalesReturnsActions.postReturnFailure({
                error: error.error?.message || 'Failed to post return',
              })
            )
          )
        )
      )
    )
  );

  cancelReturn$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesReturnsActions.cancelReturn),
      exhaustMap(({ id }) =>
        this.returnService.cancel(id).pipe(
          map((response) =>
            SalesReturnsActions.cancelReturnSuccess({ salesReturn: response.data })
          ),
          catchError((error) =>
            of(
              SalesReturnsActions.cancelReturnFailure({
                error: error.error?.message || 'Failed to cancel return',
              })
            )
          )
        )
      )
    )
  );
}
