import { inject, Injectable } from '@angular/core';

import { Store, Action, Selector, State, StateContext } from '@ngxs/store';
import { tap } from 'rxjs';

import {
  GetUserDetailsAction,
  UpdateUserProfileAction,
  UpdateUserPasswordAction,
  CreateAddressAction,
  UpdateAddressAction,
  DeleteAddressAction,
  AccountClearAction,
} from '../action/account.action';
import { AccountService } from '../services/account.service';
import { NotificationService } from '../services/notification.service';
import { IAccountUser, IAccountUserUpdatePassword } from './../interface/account.interface';

export class AccountStateModel {
  user: IAccountUser | null;
  permissions: [];
}

@State<AccountStateModel>({
  name: 'account',
  defaults: {
    user: null,
    permissions: [],
  },
})
@Injectable()
export class AccountState {
  private store = inject(Store);
  private accountService = inject(AccountService);
  private notificationService = inject(NotificationService);

  @Selector()
  static user(state: AccountStateModel) {
    return state.user;
  }

  @Selector()
  static permissions(state: AccountStateModel) {
    return state.permissions;
  }

  @Action(GetUserDetailsAction)
  getUserDetails(ctx: StateContext<AccountStateModel>) {
    return this.accountService.getUserDetails().pipe(
      tap({
        next: result => {
          ctx.patchState({
            user: result,
            permissions: result.permission,
          });
        },
        error: err => {
          throw new Error(err?.error?.message);
        },
      }),
    );
  }

  @Action(UpdateUserProfileAction)
  updateProfile(ctx: StateContext<AccountStateModel>, { payload }: UpdateUserProfileAction) {
    return this.accountService.updateProfile(payload).pipe(
      tap({
        next: result => {
          const state = ctx.getState();
          ctx.patchState({
            ...state,
            user: result,
          });
        },
        complete: () => {
          this.notificationService.showSuccess('Profile Updated Successfully.');
        },
        error: err => {
          throw new Error(err?.error?.message);
        },
      }),
    );
  }

  @Action(UpdateUserPasswordAction)
  updatePassword(
    _ctx: StateContext<IAccountUserUpdatePassword>,
    { payload }: UpdateUserPasswordAction,
  ) {
    return this.accountService.updatePassword(payload).pipe(
      tap({
        complete: () => {
          this.notificationService.showSuccess('Password Updated Successfully.');
        },
        error: err => {
          throw new Error(err?.error?.message);
        },
      }),
    );
  }

  @Action(CreateAddressAction)
  createAddress(ctx: StateContext<AccountStateModel>, action: CreateAddressAction) {
    return this.accountService.createAddress(action.payload).pipe(
      tap({
        next: result => {
          const state = ctx.getState();
          ctx.patchState({
            ...state,
            user: {
              ...state.user!,
              address: [...state.user?.address!, result],
            },
          });
        },
        complete: () => {
          this.notificationService.showSuccess('Address Added Successfully.');
        },
        error: err => {
          throw new Error(err?.error?.message);
        },
      }),
    );
  }

  @Action(UpdateAddressAction)
  updateAddress(_ctx: StateContext<AccountStateModel>, action: UpdateAddressAction) {
    return this.accountService.updateAddress(action.payload, action.id).pipe(
      tap({
        next: _result => {
          this.store.dispatch(new GetUserDetailsAction());
        },
        complete: () => {
          this.notificationService.showSuccess('Address Updated Successfully.');
        },
        error: err => {
          throw new Error(err?.error?.message);
        },
      }),
    );
  }

  @Action(DeleteAddressAction)
  deleteAddress(ctx: StateContext<AccountStateModel>, action: DeleteAddressAction) {
    return this.accountService.deleteAddress(action.id).pipe(
      tap({
        next: _result => {
          const state = ctx.getState();
          const addresses = state.user?.address?.filter(item => item.id !== action.id);
          ctx.patchState({
            user: {
              ...state.user!,
              address: addresses,
            },
          });
        },
        complete: () => {
          this.notificationService.showSuccess('Address Deleted Successfully.');
        },
        error: err => {
          throw new Error(err?.error?.message);
        },
      }),
    );
  }

  @Action(AccountClearAction)
  accountClear(ctx: StateContext<AccountStateModel>) {
    ctx.patchState({
      user: null,
      permissions: [],
    });
  }
}
