import { AsyncPipe, NgIf } from '@angular/common';
import { Component, computed, input, Input, untracked } from '@angular/core';
import { CircleButtonComponent, getConfig, HelpModeService, IqserPermissionsService } from '@iqser/common-ui';
import { AnnotationPermissions } from '@models/file/annotation.permissions';
import { AnnotationWrapper } from '@models/file/annotation.wrapper';
import { TranslateModule } from '@ngx-translate/core';
import { PermissionsService } from '@services/permissions.service';
import { Roles } from '@users/roles';
import { REDAnnotationManager } from '../../../pdf-viewer/services/annotation-manager.service';
import { AnnotationActionsService } from '../../services/annotation-actions.service';
import { AnnotationReferencesService } from '../../services/annotation-references.service';
import { FilePreviewStateService } from '../../services/file-preview-state.service';
import { MultiSelectService } from '../../services/multi-select.service';
import { SkippedService } from '../../services/skipped.service';
import { ViewModeService } from '../../services/view-mode.service';

export const AnnotationButtonTypes = {
    default: 'default',
    primary: 'primary',
} as const;

export type AnnotationButtonType = keyof typeof AnnotationButtonTypes;

@Component({
    selector: 'redaction-annotation-actions',
    templateUrl: './annotation-actions.component.html',
    styleUrls: ['./annotation-actions.component.scss'],
    standalone: true,
    imports: [CircleButtonComponent, TranslateModule, AsyncPipe, NgIf],
})
export class AnnotationActionsComponent {
    readonly #isDocumine = getConfig().IS_DOCUMINE;
    @Input() buttonType: AnnotationButtonType = AnnotationButtonTypes.default;
    @Input() tooltipPosition: 'before' | 'above' = 'before';
    @Input() canPerformAnnotationActions: boolean;
    @Input() alwaysVisible: boolean;
    @Input() actionsHelpModeKey: string;
    readonly roles = Roles;
    readonly annotations = input.required<AnnotationWrapper[], (AnnotationWrapper | undefined)[]>({
        transform: value => value.filter(a => a !== undefined),
    });
    readonly isVisible = computed(() => {
        const hidden = this._annotationManager.hidden();
        return this.annotations().reduce((acc, annotation) => !hidden.has(annotation.id) && acc, true);
    });
    readonly somePending = computed(() => {
        return this.annotations().some(a => a.pending);
    });
    readonly sameType = computed(() => {
        const annotations = this.annotations();
        const type = annotations[0].superType;
        return annotations.every(a => a.superType === type);
    });
    readonly resizing = computed(() => {
        return this.annotations().length === 1 && this.annotations()[0].id === this._annotationManager.resizingAnnotationId;
    });
    readonly viewerAnnotations = computed(() => {
        return this._annotationManager.get(this.annotations());
    });
    readonly annotationPermissions = computed(() =>
        AnnotationPermissions.forUser(
            this._permissionsService.isApprover(this._state.dossier()),
            this.annotations(),
            this._state.dictionaries,
            this._iqserPermissionsService,
            this._state.file().excludedFromAutomaticAnalysis,
        ),
    );
    readonly hideSkipped = computed(() => this.skippedService.hideSkipped() && this.annotations().some(a => a.isSkipped));
    readonly isImageHint = computed(() => this.annotations().every(a => a.IMAGE_HINT));
    readonly isImage = computed(() => this.annotations().reduce((acc, a) => acc && a.isImage, true));
    readonly annotationChangesAllowed = computed(
        () => (!this.#isDocumine || !this._state.file().excludedFromAutomaticAnalysis) && !this.somePending(),
    );
    readonly canRemoveRedaction = computed(
        () => this.annotationChangesAllowed() && this.annotationPermissions().canRemoveRedaction && this.sameType(),
    );
    readonly canForceRedaction = computed(() => this.annotationChangesAllowed() && this.annotationPermissions().canForceRedaction);
    readonly canForceHint = computed(() => this.annotationChangesAllowed() && this.annotationPermissions().canForceHint);
    readonly canAcceptRecommendation = computed(
        () => this.annotationChangesAllowed() && this.annotationPermissions().canAcceptRecommendation,
    );
    readonly canResize = computed(
        () => this.annotationChangesAllowed() && this.annotationPermissions().canResizeAnnotation && this.annotations().length === 1,
    );
    readonly canEdit = computed(() => {
        const canEditRedactions =
            this.annotationPermissions().canChangeLegalBasis ||
            this.annotationPermissions().canRecategorizeAnnotation ||
            this.annotationPermissions().canForceHint ||
            this.annotationPermissions().canForceRedaction;
        return (
            this.annotationChangesAllowed() &&
            (this.annotations().length > 1
                ? this.#isDocumine
                    ? this.annotationPermissions().canEditAnnotations
                    : this.annotationPermissions().canEditHints ||
                      this.annotationPermissions().canEditImages ||
                      this.annotationPermissions().canEditAnnotations
                : canEditRedactions)
        );
    });

    constructor(
        readonly viewModeService: ViewModeService,
        readonly helpModeService: HelpModeService,
        readonly multiSelectService: MultiSelectService,
        private readonly _state: FilePreviewStateService,
        private readonly _permissionsService: PermissionsService,
        private readonly _iqserPermissionsService: IqserPermissionsService,
        private readonly _annotationManager: REDAnnotationManager,
        readonly skippedService: SkippedService,
        readonly annotationActionsService: AnnotationActionsService,
        readonly annotationReferencesService: AnnotationReferencesService,
    ) {}

    get resized(): boolean {
        return this._annotationManager.annotationHasBeenResized;
    }

    async removeRedaction(): Promise<void> {
        const annotations = untracked(this.annotations);
        const permissions = untracked(this.annotationPermissions);
        await this.annotationActionsService.removeRedaction(annotations, permissions);
    }

    async acceptRecommendation(): Promise<void> {
        const annotations = untracked(this.annotations);
        await this.annotationActionsService.convertRecommendationToAnnotation(annotations);
    }

    hideAnnotation() {
        const viewerAnnotations = untracked(this.viewerAnnotations);
        this._annotationManager.hide(viewerAnnotations);
        this._annotationManager.deselect();
        this._annotationManager.addToHidden(viewerAnnotations[0].Id);
    }

    showAnnotation() {
        const viewerAnnotations = untracked(this.viewerAnnotations);
        this._annotationManager.show(viewerAnnotations);
        this._annotationManager.deselect();
        this._annotationManager.removeFromHidden(viewerAnnotations[0].Id);
    }

    resize() {
        const annotations = untracked(this.annotations);
        return this.annotationActionsService.resize(annotations[0]);
    }

    acceptResize() {
        if (this.resized) {
            const annotations = untracked(this.annotations);
            const permissions = untracked(this.annotationPermissions);
            return this.annotationActionsService.acceptResize(annotations[0], permissions);
        }
    }

    cancelResize() {
        const annotations = untracked(this.annotations);
        return this.annotationActionsService.cancelResize(annotations[0]);
    }

    helpModeKey(action: string) {
        return this.#isDocumine ? `${action}_annotation` : `${this.actionsHelpModeKey}_${action}`;
    }
}
