import { Component, OnInit, signal } from '@angular/core';
import {
    BaseFormComponent,
    CircleButtonComponent,
    IconButtonComponent,
    IqserDialog,
    listingProvidersFactory,
    LoadingService,
} from '@iqser/common-ui';
import { ComponentDefinitionsService } from '@services/entity-services/component-definitions.service';
import { firstValueFrom } from 'rxjs';
import { getParam } from '@common-ui/utils';
import { DOSSIER_TEMPLATE_ID, IComponentDefinition } from '@red/domain';
import { toObservable } from '@angular/core/rxjs-interop';
import { InputWithActionComponent } from '@common-ui/inputs/input-with-action/input-with-action.component';
import { CommonModule, NgIf } from '@angular/common';
import { TranslateModule } from '@ngx-translate/core';
import { PermissionsService } from '@services/permissions.service';
import { MatIcon } from '@angular/material/icon';
import { CdkDrag, CdkDragDrop, CdkDragHandle, CdkDropList, moveItemInArray } from '@angular/cdk/drag-drop';
import { FormBuilder, FormsModule, ReactiveFormsModule, Validators } from '@angular/forms';
import { AdminDialogService } from '../../services/admin-dialog.service';

@Component({
    templateUrl: './component-definitions.component.html',
    styleUrls: ['./component-definitions.component.scss'],
    providers: listingProvidersFactory(ComponentDefinitionsComponent),
    standalone: true,
    imports: [
        IconButtonComponent,
        InputWithActionComponent,
        NgIf,
        TranslateModule,
        CommonModule,
        MatIcon,
        CdkDragHandle,
        CdkDropList,
        CdkDrag,
        FormsModule,
        ReactiveFormsModule,
        CircleButtonComponent,
    ],
})
export default class ComponentDefinitionsComponent extends BaseFormComponent implements OnInit {
    readonly #dossierTemplateId = getParam(DOSSIER_TEMPLATE_ID);
    readonly #componentDefinitions = signal<IComponentDefinition[]>([]);
    protected readonly componentDefinitions$ = toObservable(this.#componentDefinitions);
    protected selectedComponent: IComponentDefinition | null = null;

    constructor(
        private readonly _loadingService: LoadingService,
        private readonly _componentDefinitionsService: ComponentDefinitionsService,
        private readonly _dialog: IqserDialog,
        private readonly _formBuilder: FormBuilder,
        private readonly _dialogService: AdminDialogService,
        protected readonly permissionsService: PermissionsService,
    ) {
        super();
    }

    async ngOnInit() {
        this._loadingService.stop();
        await this.#loadData();
    }

    async #loadData() {
        const componentDefinitions = await firstValueFrom(
            this._componentDefinitionsService.getComponentDefinitions(this.#dossierTemplateId),
        );
        this.#componentDefinitions.set(componentDefinitions);
    }

    async createEmptyComponentDefinition() {
        this.selectedComponent = {
            displayName: '',
            description: '',
        } as IComponentDefinition;
        this.initForm();
    }

    async save() {
        if (this.selectedComponent.id) {
            const component = { ...this.form.getRawValue(), id: this.selectedComponent.id };
            await firstValueFrom(this._componentDefinitionsService.updateComponentDefinition(this.#dossierTemplateId, component));
        } else {
            const component = {
                ...this.form.getRawValue(),
                dossierTemplateId: this.#dossierTemplateId,
                technicalName: this.technicalName,
            };
            await firstValueFrom(this._componentDefinitionsService.createComponentDefinition(this.#dossierTemplateId, component));
        }
        await this.#loadData();
        this.selectComponent();
        await this.initForm();
    }

    async drop(event: CdkDragDrop<string>) {
        moveItemInArray(this.#componentDefinitions(), event.previousIndex, event.currentIndex);

        const componentIds = this.#componentDefinitions().map(c => c.id);
        const componentDefinitions = await firstValueFrom(
            this._componentDefinitionsService.reorderComponentDefinitions(this.#dossierTemplateId, componentIds),
        );
        this.#componentDefinitions.set(componentDefinitions);
    }

    async deleteComponent(componentId: string) {
        this._dialogService.openDialog('confirm', null, async () => {
            await firstValueFrom(this._componentDefinitionsService.deleteComponentDefinitions(this.#dossierTemplateId, [componentId]));
            await this.#loadData();
        });
    }

    initForm() {
        this.form = this.#getForm();
        this.initialFormValue = this.form.getRawValue();
    }

    #getForm() {
        return this._formBuilder.group({
            displayName: [this.selectedComponent.displayName, Validators.required],
            description: [this.selectedComponent.description],
        });
    }

    selectComponent(component?: IComponentDefinition) {
        if (component && this.selectedComponent?.id !== component.id) {
            this.selectedComponent = component;
            this.initForm();
            return;
        }
        this.selectedComponent = null;
    }

    get technicalName() {
        return this.selectedComponent.technicalName ?? this.form.get('displayName')?.value?.toLowerCase().trim().replace(/\s+/g, '_');
    }
}
