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 { SalesCommissionService } from '../../../services/sales-commission.service';
import { SalesCommissionsActions } from './commissions.actions';
import {
  selectSalesCommissionsLoaded,
  selectSalesCommissionRulesLoaded,
} from './commissions.reducer';

@Injectable()
export class SalesCommissionsEffects {
  private actions$ = inject(Actions);
  private store = inject(Store);
  private commissionService = inject(SalesCommissionService);

  loadCommissions$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesCommissionsActions.loadCommissions),
      withLatestFrom(this.store.select(selectSalesCommissionsLoaded)),
      filter(([action, loaded]) => !!action.force || !loaded),
      exhaustMap(([action]) =>
        this.commissionService.list(action.page || 1, action.perPage || 100).pipe(
          map((response) =>
            SalesCommissionsActions.loadCommissionsSuccess({
              commissions: response.data,
              meta: response.meta,
            })
          ),
          catchError((error) =>
            of(
              SalesCommissionsActions.loadCommissionsFailure({
                error: error.error?.message || 'Failed to load commissions',
              })
            )
          )
        )
      )
    )
  );

  approveCommission$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesCommissionsActions.approveCommission),
      exhaustMap(({ id }) =>
        this.commissionService.approve(id).pipe(
          map((response) =>
            SalesCommissionsActions.approveCommissionSuccess({ commission: response.data })
          ),
          catchError((error) =>
            of(
              SalesCommissionsActions.approveCommissionFailure({
                error: error.error?.message || 'Failed to approve commission',
              })
            )
          )
        )
      )
    )
  );

  markCommissionPaid$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesCommissionsActions.markCommissionPaid),
      exhaustMap(({ id }) =>
        this.commissionService.markPaid(id).pipe(
          map((response) =>
            SalesCommissionsActions.markCommissionPaidSuccess({ commission: response.data })
          ),
          catchError((error) =>
            of(
              SalesCommissionsActions.markCommissionPaidFailure({
                error: error.error?.message || 'Failed to mark commission as paid',
              })
            )
          )
        )
      )
    )
  );

  bulkApproveCommissions$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesCommissionsActions.bulkApproveCommissions),
      exhaustMap(({ ids }) =>
        this.commissionService.bulkApprove(ids).pipe(
          map(() => SalesCommissionsActions.bulkApproveCommissionsSuccess()),
          catchError((error) =>
            of(
              SalesCommissionsActions.bulkApproveCommissionsFailure({
                error: error.error?.message || 'Failed to bulk approve commissions',
              })
            )
          )
        )
      )
    )
  );

  // Reload commissions after bulk approve
  reloadAfterBulkApprove$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesCommissionsActions.bulkApproveCommissionsSuccess),
      map(() => SalesCommissionsActions.loadCommissions({ force: true }))
    )
  );

  bulkMarkCommissionsPaid$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesCommissionsActions.bulkMarkCommissionsPaid),
      exhaustMap(({ data }) =>
        this.commissionService.bulkMarkPaid(data).pipe(
          map(() => SalesCommissionsActions.bulkMarkCommissionsPaidSuccess()),
          catchError((error) =>
            of(
              SalesCommissionsActions.bulkMarkCommissionsPaidFailure({
                error: error.error?.message || 'Failed to bulk mark commissions as paid',
              })
            )
          )
        )
      )
    )
  );

  // Reload commissions after bulk mark paid
  reloadAfterBulkMarkPaid$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesCommissionsActions.bulkMarkCommissionsPaidSuccess),
      map(() => SalesCommissionsActions.loadCommissions({ force: true }))
    )
  );

  loadRules$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesCommissionsActions.loadRules),
      withLatestFrom(this.store.select(selectSalesCommissionRulesLoaded)),
      filter(([action, loaded]) => !!action.force || !loaded),
      exhaustMap(() =>
        this.commissionService.getRules().pipe(
          map((response) =>
            SalesCommissionsActions.loadRulesSuccess({
              rules: response.data,
            })
          ),
          catchError((error) =>
            of(
              SalesCommissionsActions.loadRulesFailure({
                error: error.error?.message || 'Failed to load commission rules',
              })
            )
          )
        )
      )
    )
  );

  createRule$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesCommissionsActions.createRule),
      exhaustMap(({ data }) =>
        this.commissionService.createRule(data).pipe(
          map((response) =>
            SalesCommissionsActions.createRuleSuccess({ rule: response.data })
          ),
          catchError((error) =>
            of(
              SalesCommissionsActions.createRuleFailure({
                error: error.error?.message || 'Failed to create commission rule',
              })
            )
          )
        )
      )
    )
  );

  updateRule$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesCommissionsActions.updateRule),
      exhaustMap(({ id, data }) =>
        this.commissionService.updateRule(id, data).pipe(
          map((response) =>
            SalesCommissionsActions.updateRuleSuccess({ rule: response.data })
          ),
          catchError((error) =>
            of(
              SalesCommissionsActions.updateRuleFailure({
                error: error.error?.message || 'Failed to update commission rule',
              })
            )
          )
        )
      )
    )
  );

  deleteRule$ = createEffect(() =>
    this.actions$.pipe(
      ofType(SalesCommissionsActions.deleteRule),
      exhaustMap(({ id }) =>
        this.commissionService.deleteRule(id).pipe(
          map(() => SalesCommissionsActions.deleteRuleSuccess({ id })),
          catchError((error) =>
            of(
              SalesCommissionsActions.deleteRuleFailure({
                error: error.error?.message || 'Failed to delete commission rule',
              })
            )
          )
        )
      )
    )
  );
}
