<script lang="ts">
	import { goto } from '$app/navigation';
	import { page } from '$app/stores';
	import { api_host, authToken } from '$lib';
	import type { Appointment, AppointmentDateTimes, AppointmentInputs, AppointmentList, AppointmentTimes, WeekdayAppointment, WeekSelection } from '$lib/dbdata';
	import { authFetch, generateDateArray, getDateString, getTimeSlots } from '$lib/funcs';
	import AppointmentConfirmDialog from '$lib/modules/AppointmentConfirmDialog.svelte';
	import CreatorBaseInputs from '$lib/modules/CreatorBaseInputs.svelte';
	import CreatorInputs from '$lib/modules/CreatorInputs.svelte';
	import CreatorTimeInputs from '$lib/modules/CreatorTimeInputs.svelte';
	import moment from 'moment';
	import { onMount, tick } from 'svelte';

	let creatorInputs: AppointmentInputs[] = [{ name: '', type: 'text' }];
	let topic: string;
	let location: string;
	let selectedWeek: number = parseInt(moment().startOf("isoWeek").format("YYYYWW"), 10);
	let previousWeek: number = selectedWeek;
	let duration: number = 15;
	let dueDate: string = "";
	let description: string = "test";
	let renderTimeSelection: boolean = false;
	let appointmentSaved: boolean = false;
	let weekSelection: WeekSelection[] = generateDateArray(50);
	let endpoint: "create" | "modify" = "create";
	let appointmentId: string = "";
	let oldAppointmentTimes: AppointmentDateTimes[] = [];


	let appointmentList: AppointmentList[] = [
		{
			week: selectedWeek,
			appointments: generateAppointments(splitYearAndWeek(selectedWeek).week, splitYearAndWeek(selectedWeek).year),
		}
	];

	function splitYearAndWeek(value: number): { year: number, week: number } {
		const year = Math.floor(value / 100); // Extracts the first 4 digits (year)
		const week = value % 100; // Extracts the last 2 digits (week number)
		return { year, week };
	}

	/**
	 * Generates a JSON structure for a given calendar week with actual dates.
	 * @param weekNumber The calendar week number (1-53).
	 * @param year The year for which the week should be calculated.
	 * @returns An array of objects representing the days of the given week.
	 */
	export function generateAppointments(weekNumber: number, year: number): WeekdayAppointment[] {
		const weekdays = ['Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag'];

		// Get the first day of the given calendar week (Monday-based week system)
		const startOfWeek = moment().year(year).isoWeek(weekNumber).startOf('isoWeek');

		const appointments = weekdays.map((day, index) => ({
			name: day,
			date: startOfWeek.clone().add(index, 'days').format('YYYY-MM-DD'),
			active: false,
			times: []
		}));

		return appointments;
	}

    async function changeWeek() {
		await tick();
        console.log("changed");
		console.log(selectedWeek);
		renderTimeSelection = false;

        const ix = appointmentList.findIndex((entry) => entry.week === selectedWeek);
		if (ix === -1) {
            const tmp = {
                week: selectedWeek,
                appointments: generateAppointments(splitYearAndWeek(selectedWeek).week, splitYearAndWeek(selectedWeek).year)
            }
            appointmentList = [... appointmentList, tmp];
			selectedWeekAppointments = tmp.appointments;
			console.log("not found");
        } else {
			console.log("test");
			console.log(appointmentList);
			selectedWeekAppointments = appointmentList.find(
				(entry) => entry.week === selectedWeek
			)?.appointments;
			console.log("found and send entry");
		}
		
        
		renderTimeSelection = true;
		previousWeek = selectedWeek;
		//setTimeout(() => renderTimeSelection = false, 2000);
    }

    let selectedWeekAppointments = appointmentList.find(
		(entry) => entry.week === selectedWeek
	)?.appointments;

	$: {
		// deactivate when changing weeks to prevent override
		const ix = appointmentList.findIndex((entry) => entry.week === selectedWeek);
		if (ix !== -1 && selectedWeekAppointments !== undefined && previousWeek === selectedWeek) {
			appointmentList[ix].appointments = selectedWeekAppointments;
			console.log("updated");
			console.log(appointmentList[ix].appointments);
			//renderTimeSelection = true;
			//setTimeout(() => renderTimeSelection = false, 2000);
		}
	}

	function convertAppointmentList() {
		let times: AppointmentTimes[] = [];

		// on update match with existing booked appointments
		console.log(oldAppointmentTimes);

		appointmentList.forEach(entry => {
			entry.appointments.filter(element => element.active !== false).forEach(day => {
				day.times.forEach(time => {
					// if (!time.start || !time.end)
					times = [... times, ...getTimeSlots(day.date, time.start, time.end, duration, oldAppointmentTimes)];
				});
				
			});
		});

		return times;
	}

	async function saveAppointment() {
		if (!topic || !description || !dueDate || !location || !duration || !creatorInputs || !appointmentList) {
			return;
		}
		console.log(appointmentList);
		const convertedTimes: AppointmentTimes[] = convertAppointmentList();
		console.log(convertedTimes);

		try {
            const response = await authFetch(`${api_host}/api/users/${endpoint}`, {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    "Authorization": "Bearer " + $authToken
                },
                body: JSON.stringify({
					appointmentId: appointmentId,
                    title: topic,
					description: description,
					dueDate: dueDate,
					place: location,
					duration: duration,
					times: convertedTimes,
					inputs: creatorInputs,
					timeSpans: appointmentList
                })
            });

			appointmentSaved = response.status === 200;

			setTimeout(() => {
				appointmentSaved = false;
			}, 5000);

        } catch (error) {
            console.log(error);
        }
	}

	async function loadAppointment(appointmentId: string) {
		selectedWeekAppointments = undefined;
		const response = await fetch(`${api_host}/api/schedule?appointmentId=${appointmentId}&isUser=true`, {
			method: 'GET',
			headers: {
				'Content-Type': 'application/json'
			}
		});

		if (response.status === 404) {
			goto('/errors/404');
		}
		const resp = await response.json();
		const js: Appointment = resp;
		appointmentList = js.timeSpans;
		
		topic = js.title;
		creatorInputs = js.inputs;
		location = js.place;
		duration = js.duration;
		dueDate = getDateString(js.dueDate);
		console.log(js.dueDate);
		description = js.description;
		oldAppointmentTimes = js.times;
		endpoint = "modify";

		selectedWeekAppointments = appointmentList.find(
			(entry) => entry.week === selectedWeek
		)?.appointments;
	}

	$: console.log(dueDate);

	onMount(async () => {
		// implement editor if query id param was detected
		const id = $page.url.searchParams.get('id');
		if (id) {
			appointmentId = id;
			await loadAppointment(id);
		}
	});

	// get time slots before sending
</script>

<h3 class="center-align top-padding bottom-padding">Termine</h3>

<fieldset>
	<CreatorBaseInputs changeWeek={changeWeek} bind:weeks={weekSelection} bind:description bind:dueDate bind:topic bind:location bind:selectedWeek bind:duration />

	{#if selectedWeekAppointments}
		{#key renderTimeSelection}
			<CreatorTimeInputs bind:weekdays={selectedWeekAppointments} />	
		{/key}
	{/if}

</fieldset>

<CreatorInputs bind:creatorInputs />

<div class="grid">
	<button on:click={saveAppointment} class="top-margin s12 large">Speichern</button>
</div>

{#if appointmentSaved}
	<div class="snackbar green active">Erfolgreich gespeichert</div>
{/if}

<style>
	fieldset {
		max-width: 90%;
		margin-inline: auto;
	}
</style>
