import { DatePipe as BaseDatePipe } from '@angular/common';
import { HTTP_INTERCEPTORS } from '@angular/common/http';
import { ENVIRONMENT_INITIALIZER, ErrorHandler, inject, NgModule } from '@angular/core';
import { MatDividerModule } from '@angular/material/divider';
import { MAT_TOOLTIP_DEFAULT_OPTIONS } from '@angular/material/tooltip';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ServiceWorkerModule } from '@angular/service-worker';
import { AuthErrorComponent } from '@components/auth-error/auth-error.component';
import { BaseScreenComponent } from '@components/base-screen/base-screen.component';
import { BreadcrumbsComponent } from '@components/breadcrumbs/breadcrumbs.component';
import { DownloadsListScreenComponent } from '@components/downloads-list-screen/downloads-list-screen.component';
import { NotificationsComponent } from '@components/notifications/notifications.component';
import { DashboardSkeletonComponent } from '@components/skeleton/dashboard-skeleton/dashboard-skeleton.component';
import { DossierSkeletonComponent } from '@components/skeleton/dossier-skeleton/dossier-skeleton.component';
import { SkeletonStatsComponent } from '@components/skeleton/skeleton-stats/skeleton-stats.component';
import { SkeletonTopBarComponent } from '@components/skeleton/skeleton-top-bar/skeleton-top-bar.component';
import { SpotlightSearchComponent } from '@components/spotlight-search/spotlight-search.component';
import { TenantsMenuComponent } from '@components/tenants-menu/tenants-menu.component';
import { UserMenuComponent } from '@components/user-menu/user-menu.component';
import { environment } from '@environments/environment';
import {
    CachingModule,
    ChevronButtonComponent,
    CircleButtonComponent,
    EmptyStateComponent,
    HelpModeKey,
    HiddenActionDirective,
    IconButtonComponent,
    InputWithActionComponent,
    IqserAllowDirective,
    IqserDenyDirective,
    IqserHelpModeModule,
    IqserListingModule,
    IqserLoadingModule,
    IqserTranslateModule,
    LanguageService,
    MAX_RETRIES_ON_SERVER_ERROR,
    RoundCheckboxComponent,
    SERVER_ERROR_SKIP_PATHS,
    ServerErrorInterceptor,
    StopPropagationDirective,
} from '@iqser/common-ui';
import { CommonUiModule } from '@iqser/common-ui/lib/common-ui.module';
import { LogoComponent, SkeletonComponent, ToastComponent } from '@iqser/common-ui/lib/shared';
import { TenantPipe, TenantsModule } from '@iqser/common-ui/lib/tenants';
import { IqserUsersModule } from '@iqser/common-ui/lib/users';
import { MonacoEditorModule } from '@materia-ui/ngx-monaco-editor';
import { MissingTranslationHandler } from '@ngx-translate/core';
import { AppConfig, ILoggerConfig } from '@red/domain';
import { ConfigService } from '@services/config.service';
import { ActiveDossiersService } from '@services/dossiers/active-dossiers.service';
import { ArchivedDossiersService } from '@services/dossiers/archived-dossiers.service';
import { GlobalErrorHandler } from '@services/global-error-handler.service';
import { LoggerRulesService } from '@services/logger-rules.service';
import { DatePipe } from '@shared/pipes/date.pipe';
import { SharedModule } from '@shared/shared.module';
import { FileUploadDownloadModule } from '@upload-download/file-upload-download.module';
import { RedRoleGuard } from '@users/red-role.guard';
import { UserPreferenceService } from '@users/user-preference.service';
import { UserService } from '@users/user.service';
import { UI_CACHES } from '@utils/constants';
import { REDMissingTranslationHandler } from '@utils/missing-translations-handler';
import { LoggerModule, NgxLoggerLevel, TOKEN_LOGGER_CONFIG, TOKEN_LOGGER_RULES_SERVICE } from 'ngx-logger';
import { ToastrModule } from 'ngx-toastr';
import * as helpModeKeys from '../assets/help-mode/help-mode-keys.json';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { PdfViewerModule } from './modules/pdf-viewer/pdf-viewer.module';
import { ACTIVE_DOSSIERS_SERVICE, ARCHIVED_DOSSIERS_SERVICE } from './tokens';

export const appModuleFactory = (config: AppConfig) => {
    @NgModule({
        declarations: [
            AppComponent,
            AuthErrorComponent,
            NotificationsComponent,
            SpotlightSearchComponent,
            BreadcrumbsComponent,
            DashboardSkeletonComponent,
            DossierSkeletonComponent,
            SkeletonTopBarComponent,
            SkeletonStatsComponent,
            BaseScreenComponent,
            UserMenuComponent,
            TenantsMenuComponent,
            DownloadsListScreenComponent,
        ],
        imports: [
            BrowserModule,
            BrowserAnimationsModule,
            SharedModule,
            FileUploadDownloadModule,
            AppRoutingModule,
            MonacoEditorModule,
            CommonUiModule.forRoot({
                existingUserPreferenceService: UserPreferenceService,
                configService: ConfigService,
                configServiceFactory: () => new ConfigService(config),
            }),
            IqserUsersModule.forRoot({
                existingUserService: UserService,
                existingRoleGuard: RedRoleGuard,
            }),
            CachingModule.forRoot(UI_CACHES),
            IqserHelpModeModule.forRoot(helpModeKeys as HelpModeKey[]),
            PdfViewerModule,
            ToastrModule.forRoot({
                closeButton: true,
                enableHtml: true,
                toastComponent: ToastComponent,
                preventDuplicates: true,
                resetTimeoutOnDuplicate: true,
            }),
            TenantsModule.forRoot(),
            IqserTranslateModule.forRoot({ pathPrefix: config.BASE_TRANSLATIONS_DIRECTORY || '/assets/i18n/redact/' }),
            IqserLoadingModule.forRoot(),
            ServiceWorkerModule.register('ngsw-worker.js', { enabled: environment.production }),
            LoggerModule.forRoot(undefined, {
                ruleProvider: {
                    provide: TOKEN_LOGGER_RULES_SERVICE,
                    useClass: LoggerRulesService,
                },
                configProvider: {
                    provide: TOKEN_LOGGER_CONFIG,
                    useValue: {
                        level: environment.production ? NgxLoggerLevel.ERROR : NgxLoggerLevel.DEBUG,
                        enableSourceMaps: false,
                        timestampFormat: 'mm:ss:SSS',
                        disableFileDetails: true,
                        features: {
                            ANNOTATIONS: {
                                color: 'aqua',
                                enabled: true,
                                level: NgxLoggerLevel.DEBUG,
                            },
                            FILTERS: {
                                enabled: false,
                            },
                            TENANTS: {
                                enabled: false,
                            },
                            ROUTES: {
                                enabled: true,
                            },
                            PDF: {
                                enabled: true,
                            },
                            FILE: {
                                enabled: false,
                            },
                            CHANGES: {
                                enabled: false,
                            },
                            STATS: {
                                enabled: false,
                            },
                            REDACTION_LOG: {
                                enabled: false,
                            },
                            VIEWED_PAGES: {
                                enabled: false,
                            },
                            PAGES: {
                                enabled: false,
                            },
                            DOSSIERS_CHANGES: {
                                enabled: false,
                            },
                        },
                    } as ILoggerConfig,
                },
            }),
            CircleButtonComponent,
            EmptyStateComponent,
            SkeletonComponent,
            LogoComponent,
            HiddenActionDirective,
            StopPropagationDirective,
            InputWithActionComponent,
            RoundCheckboxComponent,
            IqserAllowDirective,
            IqserDenyDirective,
            IqserListingModule,
            IconButtonComponent,
            TenantPipe,
            MatDividerModule,
            ChevronButtonComponent,
        ],
        providers: [
            {
                provide: HTTP_INTERCEPTORS,
                multi: true,
                useClass: ServerErrorInterceptor,
            },
            {
                provide: ErrorHandler,
                useClass: GlobalErrorHandler,
            },
            {
                provide: ENVIRONMENT_INITIALIZER,
                multi: true,
                useValue: async () => {
                    const languageService = inject(LanguageService);
                    return languageService.setInitialLanguage();
                },
            },
            {
                provide: MissingTranslationHandler,
                useClass: REDMissingTranslationHandler,
            },
            {
                provide: MAX_RETRIES_ON_SERVER_ERROR,
                useFactory: () => config.MAX_RETRIES_ON_SERVER_ERROR,
            },
            {
                provide: SERVER_ERROR_SKIP_PATHS,
                useValue: ['redaction-gateway-v1/license'],
            },
            {
                provide: ACTIVE_DOSSIERS_SERVICE,
                useExisting: ActiveDossiersService,
            },
            {
                provide: ARCHIVED_DOSSIERS_SERVICE,
                useExisting: ArchivedDossiersService,
            },
            {
                provide: MAT_TOOLTIP_DEFAULT_OPTIONS,
                useValue: {
                    disableTooltipInteractivity: true,
                },
            },
            BaseDatePipe,
            DatePipe,
        ],
        bootstrap: [AppComponent],
    })
    class AppModule {}

    return AppModule;
};
