import { inject, Injectable } from '@angular/core';
import { DownloadStatus, IDownloadStatus, IDownloadStatusResponse, IPrepareDownloadRequest, IRemoveDownloadRequest } from '@red/domain';
import { firstValueFrom, Observable } from 'rxjs';
import { ConfigService } from '@services/config.service';
import { map, tap } from 'rxjs/operators';
import { EntitiesService } from '@iqser/common-ui';
import { NGXLogger } from 'ngx-logger';
import { mapEach } from '@iqser/common-ui/lib/utils';
import { TenantsService } from '@iqser/common-ui/lib/tenants';

@Injectable()
export class FileDownloadService extends EntitiesService<IDownloadStatus, DownloadStatus> {
    protected readonly _defaultModelPath = 'async/download';
    protected readonly _entityClass = DownloadStatus;
    protected readonly _tenantsService = inject(TenantsService);

    constructor(private readonly _configService: ConfigService, private readonly _logger: NGXLogger) {
        super();
    }

    async downloadFiles(request: IPrepareDownloadRequest) {
        await this.prepareDownload(request);
        return firstValueFrom(this.loadAll());
    }

    loadAll(): Observable<DownloadStatus[]> {
        return this.getStatuses().pipe(
            mapEach(entity => new DownloadStatus(entity)),
            tap(entities => this.setEntities(entities)),
        );
    }

    getStatuses(): Observable<IDownloadStatus[]> {
        return super._getOne<IDownloadStatusResponse>(['status']).pipe(map(res => res.downloadStatus));
    }

    async performDownload(status: DownloadStatus) {
        const token = await this.generateToken(status.storageId);
        const anchor = document.createElement('a');
        anchor.href = `${this._configService.values.API_URL}/redaction-gateway-v1/async/download/with-ott/${
            token.value
        }?tenantId=${encodeURIComponent(this._tenantsService.activeTenantId)}`;
        anchor.download = status.filename;
        anchor.target = '_blank';
        this._logger.info('[DOWNLOAD] Downloading with link: ', anchor.href);
        document.body.appendChild(anchor);
        anchor.click();
        document.body.removeChild(anchor);
    }

    prepareDownload(body: IPrepareDownloadRequest) {
        return firstValueFrom(this._post(body, `${this._defaultModelPath}/prepare-option`));
    }

    generateToken(storageId: string) {
        const request = this._post<{ value: string }>({ value: storageId }, `${this._defaultModelPath}/generate-ott`);
        return firstValueFrom(request);
    }

    delete(body: IRemoveDownloadRequest): Observable<unknown> {
        return super._post(body, `${this._defaultModelPath}/delete`);
    }
}
