import { inject, Injectable } from '@angular/core';
import { GenericService, Toaster } from '@iqser/common-ui';
import { EntryState, EntryStates, IEntityLog, IEntityLogEntry, ISectionGrid } from '@red/domain';
import { firstValueFrom, of } from 'rxjs';
import { catchError, map } from 'rxjs/operators';

@Injectable({
    providedIn: 'root',
})
export class EntityLogService extends GenericService<unknown> {
    readonly #toaster = inject(Toaster);
    protected readonly _defaultModelPath = '';

    async getEntityLog(dossierId: string, fileId: string) {
        const queryParams = [{ key: 'includeUnprocessed', value: true }];
        const entityLog$ = this._getOne<IEntityLog>([dossierId, fileId], 'entityLog', queryParams);
        const entityLog = await firstValueFrom(entityLog$.pipe(catchError(() => of({} as IEntityLog))));
        entityLog.entityLogEntry = this.#filterInvalidEntries(entityLog.entityLogEntry, [EntryStates.REMOVED]);
        entityLog.entityLogEntry.sort((a, b) => a.positions[0].pageNumber - b.positions[0].pageNumber);
        return entityLog;
    }

    getDelta(dossierId: string, fileId: string, analysisNumber: number) {
        const req$ = this._getOne<IEntityLog>([dossierId, fileId, analysisNumber.toString()], 'entityLog');
        return req$.pipe(
            map(entityLog => {
                entityLog.entityLogEntry = this.#filterInvalidEntries(entityLog.entityLogEntry);
                return entityLog;
            }),
            catchError(() => of({} as IEntityLog)),
        );
    }

    getSectionGrid(dossierId: string, fileId: string) {
        return this._getOne<ISectionGrid>([dossierId, fileId], 'sectionGrid');
    }

    #filterInvalidEntries(entityLogEntry: IEntityLogEntry[], invalidStates: EntryState[] = []) {
        return entityLogEntry.filter(entry => {
            entry.positions = entry.positions?.filter(p => !!p.rectangle?.length);
            const hasPositions = !!entry.positions?.length;
            const hasInvalidState = invalidStates.includes(entry.state);
            if (!hasPositions) {
                this.#toaster.devInfo(`Entry ${entry.id} was skipped because it has no position`);
            }
            return hasPositions && !hasInvalidState;
        });
    }
}
