import { Component, OnInit, AfterViewInit, QueryList, ViewChildren } from '@angular/core';
import { FormBuilder, FormGroup } from '@angular/forms';
import {
    LocationService,
    UserTripJsonld,
    UserTripService,
    UserTripEventJsonld,
    UserTripEventService,
    EventService,
} 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';

@Component({
    selector: 'app-user-trip-detail',
    templateUrl: './user-trip-detail.component.html',
    styleUrl: './user-trip-detail.component.scss'
})
export class UserTripDetailComponent implements OnInit, AfterViewInit {
    protected userTrip!: UserTripJsonld;
    protected readonly FormMode = FormMode;

    // Events related properties
    protected userTripEvents: UserTripEventJsonld[] = [];
    protected originalUserTripEvents: UserTripEventJsonld[] = []; // Original-Events zum Vergleich
    protected eventForms: FormGroup[] = [];
    protected locationColDefinitions: ListColDefinition[] = SearchSelectComponent.getDefaultColDefLocations();
    protected eventColDefinitions: ListColDefinition[] = [];

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

    constructor(
        private locationService: LocationService,
        private userTripService: UserTripService,
        private userTripEventService: UserTripEventService,
        private eventService: EventService,
        protected appHelperService: AppHelperService,
        private route: ActivatedRoute,
        private fb: FormBuilder
    ) {
        // Initialize event column definitions
        this.eventColDefinitions = SearchSelectComponent.getDefaultColDefEvents();
    }

    ngOnInit() {
        this.route.params.subscribe(params => {
            this.userTripService.userTripsIdGet(params['id']).subscribe(
                data => {
                    this.userTrip = data;
                    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();
                }
            });
        });
    }

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

    loadUserTripEvents() {
        if (!this.userTrip || !this.userTrip.id) return;

        this.userTripEventService.userTripEventsGetCollection(
            1,
            200,
            this.userTrip.id
        ).subscribe({
            next: (data) => {
                this.userTripEvents = data.member;
                this.originalUserTripEvents = [...data.member]; // Kopie der ursprünglichen Events speichern

                // Formular für jedes Event erstellen
                this.eventForms = [];
                this.userTripEvents.forEach((event, index) => {
                    const form = this.createEventForm();

                    // Formularwerte initialisieren
                    if (event.eventIri) {
                        form.get('eventIri')?.setValue(event.eventIri);
                    }
                    if (event.locationIri) {
                        form.get('locationIri')?.setValue(event.locationIri);
                    }

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

    createEventForm(): FormGroup {
        return this.fb.group({
            eventIri: [null],
            locationIri: [null]
        });
    }

    getEvents = (page: number, pageSize: number, term?: string): Observable<any> => {
        return this.eventService.eventsGetCollection(page, pageSize, undefined, term);
    }

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

    formatDateForInput(dateString: string): string {
        if (!dateString) return '';
        const date = new Date(dateString);
        return date.toISOString().split('T')[0];
    }

    formatTimeForInput(dateString: string): string {
        if (!dateString) return '';
        const date = new Date(dateString);
        return date.toTimeString().slice(0, 5);
    }

    onDateInputChange(event: Event, index: number) {
        const input = event.target as HTMLInputElement;
        const currentDate = new Date(this.userTripEvents[index].date || new Date());
        const [year, month, day] = input.value.split('-').map(Number);

        currentDate.setFullYear(year, month - 1, day);
        this.userTripEvents[index].date = currentDate.toISOString();
    }

    onTimeInputChange(event: Event, index: number) {
        const input = event.target as HTMLInputElement;
        const currentDate = new Date(this.userTripEvents[index].date || new Date());
        const [hours, minutes] = input.value.split(':').map(Number);

        currentDate.setHours(hours, minutes);
        this.userTripEvents[index].date = currentDate.toISOString();
    }

    addNewUserTripEvent() {
        // Neues leeres User-Trip-Event erstellen
        const newUserTripEvent: UserTripEventJsonld = {
            userTripIri: this.userTrip.id!,
            date: new Date().toISOString(),
            eventIri: null,
            locationIri: null,
            note: null
        };

        this.userTripEvents.push(newUserTripEvent);
        this.eventForms.push(this.createEventForm());

        // Im nächsten Event-Loop erzwingen, dass die search-select-Komponenten initialisiert werden
        setTimeout(() => {
            if (this.searchSelects) {
                const lastSelects = this.searchSelects.toArray().slice(-2);
                lastSelects.forEach(select => {
                    if (select) {
                        select.ngAfterViewInit();
                    }
                });
            }
        });
    }

    removeUserTripEvent(index: number) {
        // Nur aus dem Array entfernen, tatsächliches Löschen erfolgt beim Speichern
        this.userTripEvents.splice(index, 1);
        this.eventForms.splice(index, 1);
    }

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

        // Zuerst alle existierenden Events vom Server holen
        this.userTripEventService.userTripEventsGetCollection(
            1, 200, this.userTrip.id
        ).subscribe({
            next: (existingEvents) => {
                // IDs der existierenden Events speichern
                originalEventIds = existingEvents.member
                    .filter(event => event.id)
                    .map(event => this.appHelperService.extractId(event.id!));

                // Aktualisieren der Event- und Location-Objekte in unserem userTripEvents-Array
                this.userTripEvents.forEach((userTripEvent, index) => {
                    const eventFormValue = this.eventForms[index].get('eventIri')?.value;
                    const locationFormValue = this.eventForms[index].get('locationIri')?.value;

                    // Event setzen, wenn verfügbar
                    if (eventFormValue) {
                        if (typeof eventFormValue === 'string') {
                            userTripEvent.eventIri = eventFormValue;
                        }
                    }

                    // Location setzen, wenn verfügbar
                    if (locationFormValue) {
                        if (typeof locationFormValue === 'string') {
                            userTripEvent.locationIri = locationFormValue;
                        }
                    }
                });

                // Events filtern, die sowohl Event als auch Location haben
                const validUserTripEvents = this.userTripEvents.filter(
                    ute => ute.eventIri && ute.locationIri
                );

                if (validUserTripEvents.length === 0 && this.userTripEvents.length > 0) {
                    window.alert('Bitte stelle sicher, dass alle Events sowohl einen Event-Typ als auch einen Ort haben.');
                    return;
                }

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

                // 1. Neue Events erstellen und existierende aktualisieren
                validUserTripEvents.forEach(userTripEvent => {
                    if (userTripEvent.id) {
                        // Existierendes Event aktualisieren
                        const id = this.appHelperService.extractId(userTripEvent.id);

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

                        // Update-Promise hinzufügen
                        allPromises.push(
                            firstValueFrom(this.userTripEventService.userTripEventsIdPatch(
                                id,
                                this.appHelperService.convertJsonldToJson(userTripEvent)
                            ))
                        );
                    } else {
                        // Neues Event erstellen
                        allPromises.push(
                            firstValueFrom(this.userTripEventService.userTripEventsPost(userTripEvent))
                        );
                    }
                });

                // 2. Gelöschte Events von der Datenbank entfernen
                originalEventIds.forEach(id => {
                    allPromises.push(
                        firstValueFrom(this.userTripEventService.userTripEventsIdDelete(id))
                    );
                });

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