import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
import { MenuElement } from 'src/app/model/view/menu-element';
import { AuthService } from 'src/app/service/auth.service';
import { PermissionsEnum } from 'src/app/model/auth/permissionsEnum';
import { SidebarDataService } from 'src/app/service/sidebar.data.service';
import { UserSpace } from 'src/app/model/entities/user-space';
import { SpinnerService } from 'src/app/service/spinner.service';
import { ConfirmationDialogService } from 'src/app/service/confirmation-dialog.service';
import { Router } from '@angular/router';

@Injectable({
  providedIn: 'root',
})
export class SidebarService {
  visible$ = new BehaviorSubject<boolean>(true);
  elements$ = new BehaviorSubject<MenuElement[]>([]);

  selectedUserSpace$ = new BehaviorSubject<UserSpace | undefined | null>(
    undefined
  );
  userSpaces: UserSpace[] = [];

  constructor(
    private auth: AuthService,
    private data: SidebarDataService,
    private spinner: SpinnerService,
    private router: Router,
    private confirmation: ConfirmationDialogService
  ) {
    this.loadUserSpaces();
    this.auth.user$.subscribe(async () => {
      await this.setElements();
    });

    this.data.onChange().subscribe(() => {
      this.loadUserSpaces();
    });

    this.selectedUserSpace$.subscribe(async value => {
      // skip initial value
      if (value === undefined) {
        return;
      }

      this.setSelectedUserSpaceIdToLS(value ? value.id : 0);
      await this.setElements();
      await this.router.navigate(['/admin/urls']);
    });
  }

  loadUserSpaces() {
    this.data.getAssignedUserSpaces().subscribe(async userSpaces => {
      this.userSpaces = userSpaces;

      const storedId = this.getSelectedUserSpaceIdFromLS();

      const selectedUserSpace = userSpaces.find(x => x.id === storedId);
      if (selectedUserSpace) {
        this.selectedUserSpace$.next(selectedUserSpace);
      }
      await this.setElements();
    });
  }

  show() {
    this.visible$.next(true);
  }

  hide() {
    this.visible$.next(false);
  }

  // trust me, you'll need this async
  async setElements() {
    const isSelectedUserSpaceOwner =
      this.selectedUserSpace$.value?.owner?.id === this.auth.user$.value?.id;

    const elements: MenuElement[] = [
      {
        label: 'sidebar.user_spaces',
        icon: 'pi pi-list',
        expanded: true,
        items: [
          {
            label: 'sidebar.user_space_add',
            icon: 'pi pi-plus',
            routerLink: ['/admin/rooms/create'],
          },
          ...(this.userSpaces
            ?.filter(x => x.name != this.selectedUserSpace$.value?.name)
            .map(x => {
              return {
                label: x.name,
                icon: 'pi pi-hashtag',
                command: async () => {
                  this.spinner.show();
                  this.selectedUserSpace$.next(x);
                  await this.setElements();
                  await this.router.navigate(['/admin/urls']);
                },
              } as MenuElement;
            }) ?? []),
        ],
      },
      {
        label: this.selectedUserSpace$.value?.name || '',
        icon: 'pi pi-hashtag',
        visible: !!this.selectedUserSpace$.value,
        expanded: true,
        items: [
          {
            label: 'sidebar.user_space_edit',
            icon: 'pi pi-pencil',
            visible: isSelectedUserSpaceOwner,
            routerLink: [
              `/admin/rooms/edit/${this.selectedUserSpace$.value?.id}`,
            ],
          },
          {
            label: 'common.groups',
            icon: 'pi pi-tags',
            routerLink: ['/admin/groups'],
            visible:
              !!this.selectedUserSpace$.value ||
              (await this.auth.hasAnyPermissionLazy([PermissionsEnum.groups])),
          },
          {
            label: 'common.urls',
            icon: 'pi pi-tag',
            routerLink: ['/admin/urls'],
            visible:
              !!this.selectedUserSpace$.value ||
              (await this.auth.hasAnyPermissionLazy([
                PermissionsEnum.shortUrls,
                PermissionsEnum.shortUrlsByAssignment,
              ])),
          },
          {
            label: 'sidebar.user_space_delete',
            icon: 'pi pi-trash',
            visible: isSelectedUserSpaceOwner,
            command: () => {
              this.confirmation.confirmDialog({
                header: 'dialog.delete.header',
                message: 'dialog.delete.message',
                accept: () => {
                  if (!this.selectedUserSpace$.value) {
                    return;
                  }

                  this.spinner.show();
                  this.data
                    .delete(this.selectedUserSpace$.value)
                    .subscribe(() => {
                      this.selectedUserSpace$.next(null);
                      this.spinner.hide();
                    });
                },
                messageParams: { entity: this.selectedUserSpace$.value?.name },
              });
            },
          },
        ],
      },

      await this.sectionAdmin(),
    ];

    this.elements$.next(elements);
  }

  async sectionAdmin() {
    return {
      label: 'sidebar.administration',
      icon: 'pi pi-wrench',
      visible: await this.auth.isAdmin(),
      expanded: true,
      isSection: true,
      items: [
        {
          label: 'common.domains',
          icon: 'pi pi-sitemap',
          routerLink: ['/admin/administration/domains'],
          visible: await this.auth.hasAnyPermissionLazy([
            PermissionsEnum.domains,
          ]),
        },
        {
          label: 'sidebar.users',
          icon: 'pi pi-user',
          routerLink: ['/admin/administration/users'],
          visible: await this.auth.hasAnyPermissionLazy([
            PermissionsEnum.users,
          ]),
        },
        {
          label: 'sidebar.roles',
          icon: 'pi pi-user-edit',
          routerLink: ['/admin/administration/roles'],
          visible: await this.auth.hasAnyPermissionLazy([
            PermissionsEnum.roles,
          ]),
        },
        {
          label: 'sidebar.api_keys',
          icon: 'pi pi-key',
          routerLink: ['/admin/administration/api-keys'],
          visible: await this.auth.hasAnyPermissionLazy([
            PermissionsEnum.apiKeys,
          ]),
        },
        {
          label: 'sidebar.feature_flags',
          icon: 'pi pi-flag',
          routerLink: ['/admin/administration/feature-flags'],
          visible: await this.auth.hasAnyPermissionLazy([
            PermissionsEnum.administrator,
          ]),
        },
        {
          label: 'sidebar.settings',
          icon: 'pi pi-cog',
          routerLink: ['/admin/administration/settings'],
          visible: await this.auth.hasAnyPermissionLazy([
            PermissionsEnum.administrator,
          ]),
        },
      ],
    };
  }

  protected getSelectedUserSpaceIdFromLS() {
    const storedId = localStorage.getItem('sidebar_SelectedUserSpaceId');
    return storedId ? +storedId : null;
  }

  protected setSelectedUserSpaceIdToLS(id: number) {
    localStorage.setItem('sidebar_SelectedUserSpaceId', id.toString());
  }
}
