import { Component } from '@angular/core';
import {
    UserJsonld,
    UserService,
    UserZoneJsonld, UserZoneService,
    ZoneJsonld, ZoneService
} from "@app/core/api/v1";
import {userZoneForm} from "@app/_forms/apiForms";
import {ListColDefinition} from "@app/_components/list/list-col-definition";
import {AppHelperService} from "@app/_helpers/app-helper.service";
import {TranslateService} from "@ngx-translate/core";
import {Router} from "@angular/router";
import {SearchSelectComponent} from "@app/_components/search-select/search-select.component";
import {ListGetDataFunctionType} from "@app/_components/list/list-get-data-function-type";
import {of, switchMap} from "rxjs";
import {map} from "rxjs/operators";
import {AbstractDataFormComponent} from "@app/_components/_abstract/abstract-data-form-component";

@Component({
  selector: 'app-user-zone-form',
  templateUrl: './user-zone-form.component.html',
  styleUrl: './user-zone-form.component.scss'
})
export class UserZoneFormComponent extends AbstractDataFormComponent<UserZoneJsonld> {
    protected readonly userZoneForm = userZoneForm;
    protected userColDefinitions: ListColDefinition[];
    protected zoneColDefinitions: ListColDefinition[];
    protected user?: UserJsonld;
    protected zone?: ZoneJsonld;

    constructor(
        protected userZoneService: UserZoneService,
        protected userService: UserService,
        protected zoneService: ZoneService,
        appHelperService: AppHelperService,
        translateService: TranslateService,
        router: Router
    ) {
        super(
            userZoneForm,
            appHelperService,
            (data: UserZoneJsonld) => this.userZoneService.userZonesPost(this.appHelperService.convertJsonldToJson(data)),
            (id: string | number, data: UserZoneJsonld) =>
                this.userZoneService.userZonesIdPatch(
                    id.toString(),
                    this.appHelperService.convertJsonldToJson(data)
                ),
            (id: string | number) => userZoneService.userZonesIdDelete(id.toString()),
            translateService,
            router
        );
        this.userColDefinitions = SearchSelectComponent.getDefaultColDefUsers();
        this.zoneColDefinitions = SearchSelectComponent.getDefaultColDefZones();
    }

    override ngOnInit() {
        super.ngOnInit();

        // Setze User und Zone aus den übergebenen Daten
        if (this.data?.user && !this.user) {
            this.user = this.data?.user;
        }
        if (this.data?.zone && !this.zone) {
            this.zone = this.data?.zone;
        }

        // Validierung: Mindestens User oder Zone muss vorgegeben sein
        if (!this.user && !this.zone) {
            throw new Error('UserZoneFormComponent: Either user or zone has to be given');
        }

        // Beide gleichzeitig vorgegeben ist auch nicht erlaubt (würde keinen Sinn machen)
        if (this.user && this.zone) {
            throw new Error('UserZoneFormComponent: Either user or zone has to be given');
        }

        // Setze die FormControl-Werte wenn vorgegeben
        if (this.zone && !this.data!.zoneIri!) {
            this.data!.zoneIri = this.zone.id!;
            this.form.get('zoneIri')?.setValue(this.zone.id!);
        }
        if (this.user && !this.data!.userIri!) {
            this.data!.userIri = this.user.id!;
            this.form.get('userIri')?.setValue(this.user.id!);
        }
    }

    getUsers: ListGetDataFunctionType = (
        index: number,
        pageSize: number,
        term?: string,
    ) => {
        // Hole alle Benutzer mit isPilot=true
        return this.userService.usersGetCollection(
            index,
            pageSize,
            undefined,
            undefined,
            term,
            '{"isPilot":true}'
        ).pipe(
            switchMap(usersResponse => {
                // Wenn keine Zone vorhanden ist, gib alle Benutzer zurück
                if (!this.zone?.id) {
                    return of(usersResponse);
                }

                // Hole alle UserZones für diese Zone
                return this.userZoneService.userZonesGetCollection(
                    1,
                    100,
                    undefined,  // user
                    undefined,  // user2
                    this.zone.id,  // zone
                    undefined,
                ).pipe(
                    map(userZonesResponse => {
                        // Extrahiere die User-IDs aus den UserZones
                        const usedUserIds = new Set(
                            userZonesResponse.member?.map(
                                (userZone: UserZoneJsonld) => userZone.userIri
                            ) || []
                        );

                        // Filtere die Benutzer, die noch nicht zugeordnet sind
                        if (usersResponse.member) {
                            usersResponse.member = usersResponse.member.filter(
                                (user: UserJsonld) => !usedUserIds.has(user.id!)
                            );
                            // Aktualisiere die totalItems Anzahl
                            if (usersResponse.totalItems) {
                                usersResponse.totalItems = usersResponse.member.length;
                            }
                        }

                        return usersResponse;
                    })
                );
            })
        );
    }

    getZones: ListGetDataFunctionType = (
        index: number,
        pageSize: number,
        term?: string,
    ) => {
        return this.zoneService.zonesGetCollection(
            index,
            pageSize,
            undefined,
            undefined,
            term
        ).pipe(
            switchMap(zonesResponse => {
                // Wenn kein User vorhanden ist, gib alle Zonen zurück
                if (!this.user?.id) {
                    return of(zonesResponse);
                }

                // Hole alle UserZones für diesen User
                return this.userZoneService.userZonesGetCollection(
                    1,
                    100,
                    this.user.id,  // user
                    undefined,     // user2
                    undefined      // zone
                ).pipe(
                    map(userZonesResponse => {
                        // Extrahiere die Zone-IDs aus den UserZones
                        const usedZoneIds = new Set(
                            userZonesResponse.member?.map(
                                (userZone: UserZoneJsonld) => userZone.zoneIri
                            ) || []
                        );

                        // Filtere die Zonen, die noch nicht zugeordnet sind
                        if (zonesResponse.member) {
                            zonesResponse.member = zonesResponse.member.filter(
                                (zone: ZoneJsonld) => !usedZoneIds.has(zone.id!)
                            );
                            // Aktualisiere die totalItems Anzahl
                            if (zonesResponse.totalItems) {
                                zonesResponse.totalItems = zonesResponse.member.length;
                            }
                        }

                        return zonesResponse;
                    })
                );
            })
        );
    }
}
