import { Injectable, Injector, ProviderToken } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router } from '@angular/router';
import { FilesMapService } from '@services/files/files-map.service';
import { FilesService } from '@services/files/files.service';
import { firstValueFrom } from 'rxjs';
import { DOSSIER_ID, DOSSIER_TEMPLATE_ID } from '@red/domain';
import { DossiersService } from '@services/dossiers/dossiers.service';
import { DictionaryService } from '@services/entity-services/dictionary.service';
import { DossierDictionariesMapService } from '@services/entity-services/dossier-dictionaries-map.service';
import { TenantsService } from '@iqser/common-ui/lib/tenants';

@Injectable({ providedIn: 'root' })
export class DossierFilesGuard implements CanActivate {
    constructor(
        private readonly _injector: Injector,
        private readonly _tenantsService: TenantsService,
        private readonly _filesMapService: FilesMapService,
        private readonly _filesService: FilesService,
        private readonly _dictionaryService: DictionaryService,
        private readonly _dictionaryMapService: DossierDictionariesMapService,
        private readonly _router: Router,
    ) {}

    async canActivate(route: ActivatedRouteSnapshot): Promise<boolean> {
        const dossierId = route.paramMap.get(DOSSIER_ID);
        const dossierTemplateId = route.paramMap.get(DOSSIER_TEMPLATE_ID);
        const token: ProviderToken<DossiersService> = route.data.dossiersService;
        const dossiersService: DossiersService = this._injector.get<DossiersService>(token);

        if (!dossierId && dossierTemplateId) {
            const dossiers = dossiersService.all.filter(dossier => dossier.dossierTemplateId === dossierTemplateId);
            await Promise.all(dossiers.map(dossier => this.loadDossierData(dossier.dossierId, dossierTemplateId)));
            return true;
        }

        if (!dossiersService.has(dossierId)) {
            await this._router.navigate([`/${this._tenantsService.activeTenantId}/main`, dossierTemplateId]);
            return false;
        }

        await this.loadDossierData(dossierId, dossierTemplateId);
        return true;
    }

    async loadDossierData(dossierId: string, dossierTemplateId: string) {
        const promises = [];

        if (!this._dictionaryMapService.has(dossierId)) {
            const dictionaryPromise = this._dictionaryService.loadDossierDictionary(dossierTemplateId, dossierId);
            promises.push(dictionaryPromise);
        }

        if (!this._filesMapService.has(dossierId)) {
            promises.push(firstValueFrom(this._filesService.loadAll(dossierId)));
        }

        return Promise.all(promises);
    }
}
