import { NgComponentOutlet } from '@angular/common'
import {
  Component,
  inject,
  OnDestroy,
  OnInit,
  signal,
  Type,
  ViewChild,
} from '@angular/core'
import { ActivatedRoute, Router } from '@angular/router'
import {
  NgbDropdownModule,
  NgbNavChangeEvent,
  NgbNavModule,
} from '@ng-bootstrap/ng-bootstrap'
import { NgxBootstrapIconsModule } from 'ngx-bootstrap-icons'
import { Subject, takeUntil } from 'rxjs'
import { IfPermissionsDirective } from 'src/app/directives/if-permissions.directive'
import {
  PermissionAction,
  PermissionsService,
  PermissionType,
} from 'src/app/services/permissions.service'
import { ClearableBadgeComponent } from '../../common/clearable-badge/clearable-badge.component'
import { PageHeaderComponent } from '../../common/page-header/page-header.component'
import { CustomFieldsComponent } from './custom-fields/custom-fields.component'
import { CorrespondentListComponent } from './management-list/correspondent-list/correspondent-list.component'
import { DocumentTypeListComponent } from './management-list/document-type-list/document-type-list.component'
import { ManagementListComponent } from './management-list/management-list.component'
import { StoragePathListComponent } from './management-list/storage-path-list/storage-path-list.component'
import { TagListComponent } from './management-list/tag-list/tag-list.component'

enum DocumentAttributesNavIDs {
  Tags = 1,
  Correspondents = 2,
  DocumentTypes = 3,
  StoragePaths = 4,
  CustomFields = 5,
}

export enum DocumentAttributesSectionKind {
  ManagementList = 'managementList',
  CustomFields = 'customFields',
}

interface DocumentAttributesSection {
  id: DocumentAttributesNavIDs
  path: string
  label: string
  icon: string
  infoLink?: string
  permissionType: PermissionType
  kind: DocumentAttributesSectionKind
  component: Type<any>
}

@Component({
  selector: 'pngx-document-attributes',
  templateUrl: './document-attributes.component.html',
  styleUrls: ['./document-attributes.component.scss'],
  imports: [
    PageHeaderComponent,
    NgbNavModule,
    NgbDropdownModule,
    NgComponentOutlet,
    NgxBootstrapIconsModule,
    IfPermissionsDirective,
    ClearableBadgeComponent,
  ],
})
export class DocumentAttributesComponent implements OnInit, OnDestroy {
  private readonly permissionsService = inject(PermissionsService)
  private readonly activatedRoute = inject(ActivatedRoute)
  private readonly router = inject(Router)
  private readonly unsubscribeNotifier = new Subject<void>()

  protected readonly PermissionAction = PermissionAction
  protected readonly PermissionType = PermissionType

  readonly sections: DocumentAttributesSection[] = [
    {
      id: DocumentAttributesNavIDs.Tags,
      path: 'tags',
      label: $localize`Tags`,
      icon: 'tags',
      infoLink: 'usage/#terms-and-definitions',
      permissionType: PermissionType.Tag,
      kind: DocumentAttributesSectionKind.ManagementList,
      component: TagListComponent,
    },
    {
      id: DocumentAttributesNavIDs.Correspondents,
      path: 'correspondents',
      label: $localize`Correspondents`,
      icon: 'person',
      infoLink: 'usage/#terms-and-definitions',
      permissionType: PermissionType.Correspondent,
      kind: DocumentAttributesSectionKind.ManagementList,
      component: CorrespondentListComponent,
    },
    {
      id: DocumentAttributesNavIDs.DocumentTypes,
      path: 'documenttypes',
      label: $localize`Document types`,
      icon: 'hash',
      infoLink: 'usage/#terms-and-definitions',
      permissionType: PermissionType.DocumentType,
      kind: DocumentAttributesSectionKind.ManagementList,
      component: DocumentTypeListComponent,
    },
    {
      id: DocumentAttributesNavIDs.StoragePaths,
      path: 'storagepaths',
      label: $localize`Storage paths`,
      icon: 'folder',
      infoLink: 'usage/#terms-and-definitions',
      permissionType: PermissionType.StoragePath,
      kind: DocumentAttributesSectionKind.ManagementList,
      component: StoragePathListComponent,
    },
    {
      id: DocumentAttributesNavIDs.CustomFields,
      path: 'customfields',
      label: $localize`Custom fields`,
      icon: 'ui-radios',
      infoLink: 'usage/#custom-fields',
      permissionType: PermissionType.CustomField,
      kind: DocumentAttributesSectionKind.CustomFields,
      component: CustomFieldsComponent,
    },
  ]

  @ViewChild('activeOutlet', { read: NgComponentOutlet })
  activeOutlet: NgComponentOutlet

  readonly activeNavID = signal<number>(null)

  get visibleSections(): DocumentAttributesSection[] {
    return this.sections.filter((section) =>
      this.permissionsService.currentUserCan(
        PermissionAction.View,
        section.permissionType
      )
    )
  }

  get activeSection(): DocumentAttributesSection | null {
    return (
      this.visibleSections.find(
        (section) => section.id === this.activeNavID()
      ) ?? null
    )
  }

  get activeManagementList(): ManagementListComponent<any> | null {
    if (
      this.activeSection?.kind !== DocumentAttributesSectionKind.ManagementList
    )
      return null
    const instance = this.activeOutlet?.componentInstance
    return instance instanceof ManagementListComponent ? instance : null
  }

  get activeCustomFields(): CustomFieldsComponent | null {
    if (!this.customFieldsActive) return null
    const instance = this.activeOutlet?.componentInstance
    return instance instanceof CustomFieldsComponent ? instance : null
  }

  get customFieldsActive(): boolean {
    return (
      this.activeSection?.kind === DocumentAttributesSectionKind.CustomFields
    )
  }

  get activeTabLabel(): string {
    return this.activeSection?.label ?? ''
  }

  get activeInfoLink(): string {
    return this.activeSection?.infoLink ?? null
  }

  get activeHeaderLoading(): boolean {
    return (
      this.activeManagementList?.loading() ??
      this.activeCustomFields?.loading() ??
      false
    )
  }

  ngOnInit(): void {
    this.activatedRoute.paramMap
      .pipe(takeUntil(this.unsubscribeNotifier))
      .subscribe((paramMap) => {
        const section = paramMap.get('section')
        const navIDFromSection =
          this.getNavIDForSection(section) ?? this.getDefaultNavID()

        if (navIDFromSection == null) {
          this.router.navigate(['/dashboard'], { replaceUrl: true })
          return
        }

        if (this.activeNavID() !== navIDFromSection) {
          this.activeNavID.set(navIDFromSection)
        }

        if (!section || this.getNavIDForSection(section) == null) {
          this.router.navigate(
            ['attributes', this.getSectionForNavID(this.activeNavID())],
            { replaceUrl: true }
          )
        }
      })
  }

  ngOnDestroy(): void {
    this.unsubscribeNotifier.next()
    this.unsubscribeNotifier.complete()
  }

  onNavChange(navChangeEvent: NgbNavChangeEvent): void {
    const nextSection = this.getSectionForNavID(navChangeEvent.nextId)
    if (!nextSection) {
      return
    }
    this.router.navigate(['attributes', nextSection])
  }

  addCustomField(): void {
    this.activeCustomFields?.editField(null)
  }

  private getDefaultNavID(): DocumentAttributesNavIDs | null {
    return this.visibleSections[0]?.id ?? null
  }

  private getNavIDForSection(section: string): DocumentAttributesNavIDs | null {
    const path = section?.toLowerCase()
    if (!path) return null

    const found = this.visibleSections.find((s) => s.path === path)
    return found?.id ?? null
  }

  private getSectionForNavID(navID: number): string | null {
    const section = this.visibleSections.find((s) => s.id === navID)
    return section?.path ?? null
  }
}
