import { inject, Injectable } from '@angular/core';
import { EntitiesService, Toaster } from '@iqser/common-ui';
import { DossierState, IDossierState } from '@red/domain';
import { EMPTY, firstValueFrom, forkJoin, Observable, switchMap } from 'rxjs';
import { DossierTemplatesService } from '../dossier-templates/dossier-templates.service';
import { catchError, defaultIfEmpty, tap } from 'rxjs/operators';
import { DossierStatesMapService } from '../entity-services/dossier-states-map.service';
import { HttpErrorResponse, HttpStatusCode } from '@angular/common/http';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { mapEach } from '@iqser/common-ui/lib/utils';

const CONFLICT_MSG = _('dossier-states-listing.error.conflict');
const GENERIC_MSG = _('dossier-states-listing.error.generic');

@Injectable({
    providedIn: 'root',
})
export class DossierStatesService extends EntitiesService<IDossierState, DossierState> {
    readonly #toaster = inject(Toaster);
    readonly #dossierTemplatesService = inject(DossierTemplatesService);
    readonly #dossierStatesMapService = inject(DossierStatesMapService);
    protected readonly _defaultModelPath = 'dossier-status';
    protected readonly _entityClass = DossierState;

    async createOrUpdate(state: IDossierState) {
        const showToast = (error: HttpErrorResponse) => {
            this.#toaster.error(error.status === HttpStatusCode.Conflict ? CONFLICT_MSG : GENERIC_MSG);
            return EMPTY;
        };

        const request = this._post(state, this._defaultModelPath).pipe(
            catchError(showToast),
            switchMap(() => this.loadAllForTemplate(state.dossierTemplateId)),
        );

        return firstValueFrom(request);
    }

    loadAllForTemplate(templateId: string) {
        return this.loadAll(`${this._defaultModelPath}/dossier-template/${templateId}`).pipe(
            tap(states => this.#dossierStatesMapService.set(templateId, states)),
        );
    }

    loadAllForAllTemplates(): Observable<DossierState[][]> {
        return this.#dossierTemplatesService.all$.pipe(
            mapEach(template => template.dossierTemplateId),
            mapEach(id => this.loadAllForTemplate(id)),
            switchMap(all => forkJoin(all).pipe(defaultIfEmpty([] as DossierState[][]))),
        );
    }

    async deleteState(dossierState: IDossierState, replaceDossierStatusId?: string) {
        const queryParams = replaceDossierStatusId ? [{ key: 'replaceDossierStatusId', value: replaceDossierStatusId }] : null;
        await firstValueFrom(super.delete(dossierState.dossierStatusId, this._defaultModelPath, queryParams));
        return firstValueFrom(this.loadAllForTemplate(dossierState.dossierTemplateId));
    }
}
