import { Component, OnInit, AfterViewInit, QueryList, ViewChildren } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import {
    TripJsonld,
    TripLocationJsonld,
    TripLocationService,
    TripService,
    LocationService,
    LocationJsonld,
    UserTripService, UserService, UserTripJsonld, UserJsonld, UserTripEventJsonld, UserTripEventService, TripLocation
} from "@app/core/api/v1";
import { AppHelperService } from "@app/_helpers/app-helper.service";
import { ActivatedRoute } from "@angular/router";
import { FormMode, FormSubmitEvent } from "@app/_components/_abstract/abstract-data-form-component";
import { ModalStatus } from "@app/_helpers/modal.states";
import {firstValueFrom, Observable} from 'rxjs';
import { ListColDefinition } from '@app/_components/list/list-col-definition';
import { SearchSelectComponent } from '@app/_components/search-select/search-select.component';
import {map} from "rxjs/operators";
import {TranslateService} from "@ngx-translate/core";

@Component({
    selector: 'app-trip-detail',
    templateUrl: './trip-detail.component.html',
    styleUrl: './trip-detail.component.scss'
})
export class TripDetailComponent implements OnInit, AfterViewInit {
    protected trip!: TripJsonld;
    protected readonly FormMode = FormMode;
    protected originalUserTrips: UserTripJsonld[] = [];
    protected tripLocations: TripLocationJsonld[] = [];
    protected userTrips: UserTripJsonld[] = [];
    protected userTripEvents: UserTripEventJsonld[] = [];
    protected users: UserJsonld[] = [];
    protected locationForms: FormGroup[] = [];
    protected locationColDefinitions: ListColDefinition[] = SearchSelectComponent.getDefaultColDefLocations();
    protected userForms: FormGroup[] = [];
    protected userColDefinitions: ListColDefinition[] = SearchSelectComponent.getDefaultColDefUsers();
    protected originalTripLocations: TripLocation[] = [];


    @ViewChildren(SearchSelectComponent) searchSelects!: QueryList<SearchSelectComponent>;

    constructor(
        private tripService: TripService,
        private tripLocationService: TripLocationService,
        private locationService: LocationService,
        private userTripService: UserTripService,
        private userTripEventService: UserTripEventService,
        private userService: UserService,
        protected appHelperService: AppHelperService,
        protected translateService: TranslateService,
        private route: ActivatedRoute,
        private fb: FormBuilder
    ) {}

    ngOnInit() {
        this.route.params.subscribe(params => {
            this.tripService.tripsIdGet(params['id']).subscribe(
                data => {
                    this.trip = data;
                    this.loadTripLocations();
                    this.loadUserTrips();
                    this.loadUserTripEvents();
                }
            );
        });
    }

    ngAfterViewInit() {
        // Reinitialize search selects when they change
        this.searchSelects.changes.subscribe(components => {
            components.forEach((component: SearchSelectComponent) => {
                // Force search selects to initialize
                if (component.dataSet) {
                    component.ngAfterViewInit();
                }
            });
        });
    }

    loadTripLocations() {
        this.tripLocationService.tripLocationsGetCollection(
            1,
            200,
            this.trip !== undefined ? this.trip.id : undefined,
        ).subscribe(
            data => {
                this.tripLocations = data.member;
                // Create a form for each trip location
                this.locationForms = [];
                this.originalTripLocations = JSON.parse(JSON.stringify(this.tripLocations));
                this.tripLocations.forEach((tripLocation) => {
                    this.locationForms.push(this.createLocationForm(tripLocation.location?.id ?? null));
                });
            }
        );
    }

    createLocationForm(locationIri: string | null): FormGroup {
        return this.fb.group({
            location: [locationIri]
        });
    }

    createUserForm(): FormGroup {
        return this.fb.group({
            user: [null]
        });
    }

    getLocations = (page: number, pageSize: number, term?: string): Observable<any> => {
        return this.locationService.locationsGetCollection(page, pageSize, term);
    }

    getUsers = (page: number, pageSize: number, term?: string): Observable<any> => {
        // Sammeln Sie alle aktuell ausgewählten Benutzer-IDs (sowohl gespeicherte als auch nicht gespeicherte)
        const assignedUserIds: string[] = [];

        // IDs aus bestehenden UserTrips (mit gültiger ID)
        this.userTrips
            .filter(ut => ut.user && ut.user.id)
            .forEach(ut => assignedUserIds.push(this.appHelperService.extractId(ut.user?.id!)));

        // IDs aus aktuellen Formularwerten (auch für noch nicht gespeicherte Einträge)
        this.userForms.forEach(form => {
            const userValue = form.get('user')?.value;
            if (userValue) {
                assignedUserIds.push(this.appHelperService.extractId(userValue));
            }
        });

        // Filtere Benutzer, die bereits ausgewählt sind (gespeichert oder nicht)
        return this.userService.usersGetCollection(
            page,
            pageSize,
            undefined,
            undefined,
            term,
            '{"isPilot":true}'
        ).pipe(
            map(response => {
                response.member = response.member.filter(user =>
                    !assignedUserIds.includes(this.appHelperService.extractId(user.id!))
                );
                return response;
            })
        );
    }

    onUserSelectChange(index: number) {
        // Erzwingen Sie eine Aktualisierung aller anderen SearchSelect-Komponenten
        setTimeout(() => {
            if (this.searchSelects) {
                this.searchSelects.forEach((component, i) => {
                    // Überspringen Sie das aktuelle SearchSelect (es muss nicht aktualisiert werden)
                    if (i !== index) {
                        component.ngAfterViewInit();
                    }
                });
            }
        });
    }

    onFormUpdate(event: FormSubmitEvent<TripJsonld>) {
        if (event.status === ModalStatus.Submitted && event.data) {
            this.trip = event.data;
        }
    }

    addNewUserTrip() {
        // Erstelle ein unvollständiges Objekt (ohne user-Property)
        const newUserTrip: UserTripJsonld = {
            tripIri: this.trip.id!,
            userIri: null,
            completed: false,
            approved: false,
        };

        // Füge es als UserTripJsonld hinzu
        this.userTrips.push(newUserTrip as UserTripJsonld);
        this.userForms.push(this.createUserForm());

        // Rest unverändert...
        setTimeout(() => {
            if (this.searchSelects) {
                const lastSelect = this.searchSelects.last;
                if (lastSelect) {
                    lastSelect.ngAfterViewInit();
                }
            }
        });
    }

    loadUserTrips() {
        this.userTripService.userTripsGetCollection(
            1,
            200,
            this.trip !== undefined ? this.trip.id : undefined,
        ).subscribe({
            next: (data) => {
                this.userTrips = data.member;
                this.originalUserTrips = [...data.member]; // Kopie der ursprünglichen UserTrips speichern

                // Formulare für jeden UserTrip erstellen
                this.userForms = [];
                this.userTrips.forEach((userTrip, index) => {
                    const form = this.createUserForm();

                    // Formularwerte initialisieren
                    if (userTrip.userIri || (userTrip.user && userTrip.user.id)) {
                        form.get('user')?.setValue(userTrip.userIri || userTrip.user?.id);
                    }

                    this.userForms.push(form);
                });
            },
            error: (error) => {
                console.error('Fehler beim Laden der Benutzerzuweisungen:', error);
            }
        });
    }

    loadUserTripEvents() {
        this.userTripEventService.userTripEventsGetCollection(
            1,
            200,
            undefined,
            undefined,
            this.trip.dbId!,
        ).subscribe({
            next: (data) => {
                this.userTripEvents = data.member;
            }
        })
    }

    saveAllUserTrips() {
        // Aktuelle IDs speichern, um später gelöschte Einträge zu identifizieren
        let originalUserTripIds: string[] = [];

        // Zuerst alle existierenden UserTrips vom Server holen
        this.userTripService.userTripsGetCollection(
            1, 200, this.trip.dbId?.toString()
        ).subscribe({
            next: (existingUserTrips) => {
                // IDs der existierenden UserTrips speichern
                originalUserTripIds = existingUserTrips.member
                    .filter(userTrip => userTrip.id)
                    .map(userTrip => this.appHelperService.extractId(userTrip.id!));

                // Aktualisieren der user objects in unserem userTrips-Array
                this.userTrips.forEach((userTrip, index) => {
                    const userFormValue = this.userForms[index].get('user')?.value;

                    // User setzen, wenn verfügbar
                    if (userFormValue) {
                        if (typeof userFormValue === 'string') {
                            userTrip.userIri = userFormValue;
                        }
                    }
                });

                // Filtern: Nur UserTrips mit gültigen User-Zuweisungen behalten
                const validUserTrips = this.userTrips.filter(ut => ut.userIri || (ut.user && ut.user.id));

                if (validUserTrips.length === 0 && this.userTrips.length > 0) {
                    window.alert('Bitte wähle für jeden Eintrag einen Benutzer aus oder entferne ungenutzte Einträge.');
                    return;
                }

                // Array für alle Operationen erstellen
                const allPromises: Promise<any>[] = [];

                // 1. Neue UserTrips erstellen und existierende aktualisieren
                validUserTrips.forEach(userTrip => {
                    if (userTrip.id) {
                        // Existierenden UserTrip aktualisieren
                        const id = this.appHelperService.extractId(userTrip.id);

                        // ID aus der Liste der zu löschenden IDs entfernen
                        const idIndex = originalUserTripIds.indexOf(id);
                        if (idIndex > -1) {
                            originalUserTripIds.splice(idIndex, 1);
                        }

                        // Update-Promise hinzufügen
                        allPromises.push(
                            firstValueFrom(this.userTripService.userTripsIdPatch(
                                id,
                                this.appHelperService.convertJsonldToJson(userTrip)
                            ))
                        );
                    } else {
                        // Neuen UserTrip erstellen
                        allPromises.push(
                            firstValueFrom(this.userTripService.userTripsPost(userTrip))
                        );
                    }
                });

                // 2. Gelöschte UserTrips von der Datenbank entfernen
                originalUserTripIds.forEach(id => {
                    allPromises.push(
                        firstValueFrom(this.userTripService.userTripsIdDelete(id))
                    );
                });

                // Alle Operationen ausführen
                Promise.all(allPromises)
                    .then(() => {
                        // Nach dem Speichern alle UserTrips neu laden
                        this.loadUserTrips();
                    })
                    .catch(error => {
                        console.error('Fehler beim Speichern der Benutzerzuweisungen:', error);
                        window.alert('Beim Speichern der Benutzerzuweisungen ist ein Fehler aufgetreten. Bitte versuche es erneut.');
                    });
            },
            error: (error) => {
                console.error('Fehler beim Laden der existierenden Benutzerzuweisungen:', error);
                window.alert('Die aktuellen Benutzerzuweisungen konnten nicht geladen werden. Bitte versuche es erneut.');
            }
        });
    }
}