import { NgForOf, NgIf } from '@angular/common';
import { Component, computed, ViewChild } from '@angular/core';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import { InputWithActionComponent } from '@common-ui/inputs/input-with-action/input-with-action.component';
import { CircleButtonComponent, HasScrollbarDirective, LoadingService, Toaster } from '@iqser/common-ui';
import { TranslateModule } from '@ngx-translate/core';
import { IPageRange } from '@red/domain';
import { PermissionsService } from '@services/permissions.service';
import { ReanalysisService } from '@services/reanalysis.service';
import { extractPageRanges } from '@utils/page-ranges-mapper';
import { FilePreviewStateService } from '../../services/file-preview-state.service';

@Component({
    selector: 'redaction-page-exclusion',
    templateUrl: './page-exclusion.component.html',
    styleUrls: ['./page-exclusion.component.scss'],
    standalone: true,
    imports: [InputWithActionComponent, TranslateModule, NgIf, HasScrollbarDirective, NgForOf, CircleButtonComponent],
})
export class PageExclusionComponent {
    @ViewChild(InputWithActionComponent) private readonly _inputComponent: InputWithActionComponent;
    readonly excludedRanges = computed(() => {
        const file = this._state.file();
        const sorted = [...file.excludedPages].sort((p1, p2) => p1 - p2);
        return this._toPageRange(sorted);
    });
    readonly canExcludePages = computed(() => this.permissionsService.canExcludePages(this._state.file(), this._state.dossier()));
    readonly noExcludedAndCantExclude = computed(() => !this.canExcludePages() && !this.excludedRanges().length);

    constructor(
        readonly permissionsService: PermissionsService,
        private readonly _reanalysisService: ReanalysisService,
        private readonly _toaster: Toaster,
        private readonly _loadingService: LoadingService,
        private readonly _state: FilePreviewStateService,
    ) {}

    async excludePagesRange(inputValue: string): Promise<void> {
        this._loadingService.start();
        const file = this._state.file();
        try {
            const pageRanges = extractPageRanges(inputValue, file);
            await this._reanalysisService.excludePages({ pageRanges }, file);
            this._state.excludedPages.update(value => [...value, ...this.flattenPageRanges(pageRanges)]);
            this._inputComponent.reset();
        } catch (e) {
            this._toaster.error(_('file-preview.tabs.exclude-pages.error'));
        }
        this._loadingService.stop();
    }

    async includePagesRange(range: IPageRange): Promise<void> {
        this._loadingService.start();
        await this._reanalysisService.includePages({ pageRanges: [range] }, this._state.file());
        this._state.excludedPages.update(value => value.filter(page => !this.flattenPageRanges([range]).includes(page)));
        this._inputComponent.reset();
        this._loadingService.stop();
    }

    flattenPageRanges(ranges: IPageRange[]) {
        const flattenedPages = [];
        ranges.forEach(range => {
            for (let page = range.startPage; page <= range.endPage; page++) {
                flattenedPages.push(page);
            }
        });

        return flattenedPages;
    }

    private _toPageRange(pages: number[]) {
        return pages.reduce((ranges: IPageRange[], page) => {
            if (!ranges.length) {
                return [{ startPage: page, endPage: page }];
            }

            if (page === Number(ranges[ranges.length - 1].endPage) + 1) {
                ranges[ranges.length - 1].endPage = page;
            } else {
                ranges.push({ startPage: page, endPage: page });
            }
            return ranges;
        }, []);
    }
}
