import { Injectable, inject } from '@angular/core';
import { Actions, createEffect, ofType } from '@ngrx/effects';
import { Store } from '@ngrx/store';
import { of, EMPTY } from 'rxjs';
import { map, exhaustMap, catchError, withLatestFrom, filter } from 'rxjs/operators';
import { AccountService } from '../../services/account.service';
import { AccountsActions } from './accounts.actions';
import { selectAccountsLoaded } from './accounts.reducer';

@Injectable()
export class AccountsEffects {
  private actions$ = inject(Actions);
  private store = inject(Store);
  private accountService = inject(AccountService);

  loadAccounts$ = createEffect(() =>
    this.actions$.pipe(
      ofType(AccountsActions.loadAccounts),
      withLatestFrom(this.store.select(selectAccountsLoaded)),
      filter(([action, loaded]) => !!action.force || !loaded),
      exhaustMap(() =>
        this.accountService.listAll().pipe(
          map((response) =>
            AccountsActions.loadAccountsSuccess({ accounts: response.data, meta: response.meta })
          ),
          catchError((error) =>
            of(AccountsActions.loadAccountsFailure({ error: error.error?.message || 'Failed to load accounts' }))
          )
        )
      )
    )
  );

  createAccount$ = createEffect(() =>
    this.actions$.pipe(
      ofType(AccountsActions.createAccount),
      exhaustMap(({ account }) =>
        this.accountService.create(account).pipe(
          map((response) => AccountsActions.createAccountSuccess({ account: response.data })),
          catchError((error) =>
            of(AccountsActions.createAccountFailure({ error: error.error?.message || 'Failed to create account' }))
          )
        )
      )
    )
  );

  updateAccount$ = createEffect(() =>
    this.actions$.pipe(
      ofType(AccountsActions.updateAccount),
      exhaustMap(({ id, account }) =>
        this.accountService.update(id, account).pipe(
          map((response) => AccountsActions.updateAccountSuccess({ account: response.data })),
          catchError((error) =>
            of(AccountsActions.updateAccountFailure({ error: error.error?.message || 'Failed to update account' }))
          )
        )
      )
    )
  );

  deleteAccount$ = createEffect(() =>
    this.actions$.pipe(
      ofType(AccountsActions.deleteAccount),
      exhaustMap(({ id }) =>
        this.accountService.delete(id).pipe(
          map(() => AccountsActions.deleteAccountSuccess({ id })),
          catchError((error) =>
            of(AccountsActions.deleteAccountFailure({ error: error.error?.message || 'Failed to delete account' }))
          )
        )
      )
    )
  );
}
