import { AsyncPipe, NgForOf, NgIf, NgTemplateOutlet } from '@angular/common';
import { Component, EventEmitter, Input, Output } from '@angular/core';
import { marker as _ } from '@biesbjerg/ngx-translate-extract-marker';
import {
    CircleButtonComponent,
    CircleButtonTypes,
    getConfig,
    IqserAllowDirective,
    IqserLoadingModule,
    ProgressBarConfigModel,
    Toaster,
} from '@iqser/common-ui';
import { FilterService, INestedFilter } from '@iqser/common-ui/lib/filtering';
import { getCurrentUser, InitialsAvatarComponent } from '@iqser/common-ui/lib/users';
import { ContextComponent, getParam, IqserTooltipPositions, shareLast } from '@iqser/common-ui/lib/utils';
import { TranslateModule } from '@ngx-translate/core';
import {
    DonutChartConfig,
    Dossier,
    DOSSIER_ID,
    DossierAttributeWithValue,
    DossierStats,
    File,
    IDossierRequest,
    ProcessingTypes,
    StatusSorter,
    User,
} from '@red/domain';
import { DossierStatsService } from '@services/dossiers/dossier-stats.service';
import { DossiersService } from '@services/dossiers/dossiers.service';
import { FilesMapService } from '@services/files/files-map.service';
import { TranslateChartService } from '@services/translate-chart.service';
import { AssignUserDropdownComponent } from '@shared/components/assign-user-dropdown/assign-user-dropdown.component';
import { DonutChartComponent } from '@shared/components/donut-chart/donut-chart.component';
import { TeamMembersComponent } from '@shared/components/team-members/team-members.component';
import { TypeFilterComponent } from '@shared/components/type-filter/type-filter.component';
import { workflowFileStatusTranslations } from '@translations/file-status-translations';
import { Roles } from '@users/roles';
import { UserService } from '@users/user.service';
import { combineLatestWith, firstValueFrom } from 'rxjs';
import { map, tap } from 'rxjs/operators';
import { DossierDetailsStatsComponent } from '../dossier-details-stats/dossier-details-stats.component';

interface DossierDetailsContext {
    needsWorkFilters: INestedFilter[] | undefined;
    dossier: Dossier;
    dossierStats: DossierStats;
    statusConfig: ProgressBarConfigModel[];
}

@Component({
    selector: 'redaction-dossier-details',
    templateUrl: './dossier-details.component.html',
    styleUrls: ['./dossier-details.component.scss'],
    standalone: true,
    imports: [
        NgTemplateOutlet,
        NgIf,
        AsyncPipe,
        CircleButtonComponent,
        IqserAllowDirective,
        TranslateModule,
        DonutChartComponent,
        IqserLoadingModule,
        NgForOf,
        TypeFilterComponent,
        DossierDetailsStatsComponent,
        AssignUserDropdownComponent,
        InitialsAvatarComponent,
        TeamMembersComponent,
    ],
})
export class DossierDetailsComponent extends ContextComponent<DossierDetailsContext> {
    #currentChartSubtitleIndex = 0;
    readonly #dossierId = getParam(DOSSIER_ID);
    protected readonly circleButtonTypes = CircleButtonTypes;
    @Input() dossierAttributes: DossierAttributeWithValue[];
    @Output() readonly toggleCollapse = new EventEmitter();
    editingOwner = false;
    readonly roles = Roles;
    readonly currentUser = getCurrentUser<User>();
    readonly collapseTooltip = _('dossier-details.collapse');
    readonly expandTooltip = _('dossier-details.expand');
    chartConfig: DonutChartConfig[] = [];
    readonly isDocumine = getConfig().IS_DOCUMINE;
    readonly IqserTooltipPositions = IqserTooltipPositions;

    constructor(
        private readonly _toaster: Toaster,
        private readonly _userService: UserService,
        private readonly _dossiersService: DossiersService,
        private readonly _filesMapService: FilesMapService,
        readonly dossierStatsService: DossierStatsService,
        readonly filterService: FilterService,
        readonly translateChartService: TranslateChartService,
    ) {
        super();
        const dossier$ = _dossiersService.getEntityChanged$(this.#dossierId).pipe(shareLast());
        const filesChanged$ = _filesMapService.watchChanged$(this.#dossierId).pipe(shareLast());
        const dossierStats$ = dossierStatsService.watch$(this.#dossierId).pipe(shareLast());
        const dossierStatsWithEffects$ = dossierStats$.pipe(
            combineLatestWith(filesChanged$),
            tap(([stats]) => this.#calculateChartConfig(stats)),
            map(([stats]) => stats),
        );
        const statusConfig$ = dossierStats$.pipe(map(stats => this.#calculateStatusConfig(stats)));

        super._initContext({
            needsWorkFilters: filterService.getFilterModels$('needsWorkFilters'),
            dossier: dossier$,
            dossierStats: dossierStatsWithEffects$,
            statusConfig: statusConfig$,
        });
    }

    get managers() {
        return this._userService.all.filter(u => u.isManager).map(u => u.id);
    }

    async assignOwner(user: User | string, dossier: Dossier) {
        const owner = typeof user === 'string' ? this._userService.find(user) : user;
        const dossierRequest: IDossierRequest = { ...dossier, ownerId: owner.id };
        await firstValueFrom(this._dossiersService.createOrUpdate(dossierRequest));

        const ownerName = this._userService.getName(owner.id);
        const dossierName = dossier.dossierName;
        this._toaster.success(_('assignment.owner'), { params: { ownerName, dossierName } });
    }

    onSubtitleChanged(subtitleIndex: number) {
        this.#currentChartSubtitleIndex = subtitleIndex;
        this.#calculateChartConfig(this.dossierStatsService.get(this.#dossierId));
    }

    #calculateChartConfig(stats: DossierStats): void {
        const documentsChartConfig: DonutChartConfig[] = Object.keys(stats.fileCountPerWorkflowStatus).map(status => ({
            value: !this.#currentChartSubtitleIndex
                ? stats.fileCountPerWorkflowStatus[status]
                : this.#getPageCountPerWorkflowStatus(status),
            color: status,
            label: workflowFileStatusTranslations[status],
            key: status,
        }));
        documentsChartConfig.sort((a, b) => StatusSorter.byStatus(a.key, b.key));
        this.chartConfig = this.translateChartService.translateLabels(documentsChartConfig);
    }

    #getPageCountPerWorkflowStatus(status: string) {
        const files = this._filesMapService.get(this.#dossierId);
        return files
            .filter((file: File) => file.workflowStatus === status)
            .reduce((sum: number, file: File) => sum + file.numberOfPages, 0);
    }

    #calculateStatusConfig(stats: DossierStats): ProgressBarConfigModel[] {
        return [
            {
                id: ProcessingTypes.pending,
                label: _('processing-status.pending'),
                total: stats.numberOfFiles,
                count: stats.processingStats.pending,
                icon: 'red:reanalyse',
            },
            {
                id: ProcessingTypes.ocr,
                label: _('processing-status.ocr'),
                total: stats.numberOfFiles,
                count: stats.processingStats.ocr,
                icon: 'iqser:ocr',
            },
            {
                id: ProcessingTypes.processing,
                label: _('processing-status.processing'),
                total: stats.numberOfFiles,
                count: stats.processingStats.processing,
                icon: 'red:reanalyse',
            },
            {
                id: ProcessingTypes.processed,
                label: _('processing-status.processed'),
                total: stats.numberOfFiles,
                count: stats.processingStats.processed,
                icon: 'red:ready-for-approval',
            },
        ].filter(config => config.count > 0);
    }
}
