<script lang="ts">
	import Composite from './Composite.svelte';
	import components from '$lib/componentLoader';
	import services from '$lib/servicesLoader';
	import { createComponentStore, getComponentStore } from '$lib/stores/componentStores.ts';

	export let componentsData = {
		layout: '',
		children: []
	};

	function initializeComponentState(child) {
		child.store = createComponentStore(child.id, child.state || {});

		if (child.children) {
			child.children.forEach(initializeComponentState);
		}
	}

	$: if (componentsData && componentsData.children) {
		componentsData.children.forEach(initializeComponentState);
	}

	function mapAndSubscribe(component) {
		console.log('Mapping and subscribing for:', component.id); // Debug line

		if (component.map) {
			const localStore = getComponentStore(component.id);

			for (const [localKey, external] of Object.entries(component.map)) {
				const [externalID, externalKey] = external.split('.').map((item) => item.trim());
				const externalStore = getComponentStore(externalID);
				if (externalStore) {
					externalStore.subscribe((externalState) => {
						console.log('External state:', externalState); // Debug line
						if (externalState && externalKey in externalState) {
							localStore.update((storeValue) => {
								storeValue = storeValue || {};
								if (storeValue[localKey] !== externalState[externalKey]) {
									storeValue[localKey] = externalState[externalKey];
									return storeValue;
								}
								return storeValue;
							});
						}
					});
				}
			}
		}

		if (component.children) {
			component.children.forEach(mapAndSubscribe);
		}
	}

	$: if (componentsData && componentsData.children) {
		componentsData.children.forEach(mapAndSubscribe);
	}

	async function getComponent(componentName) {
		if (components[componentName]) {
			const module = await components[componentName]();
			return module.default;
		}
		return null;
	}

	async function loadService(serviceName) {
		if (services[serviceName]) {
			const module = await services[serviceName]();
			return module.default || module;
		}
		return null;
	}
	async function getServiceProps(component) {
		const loadedServices = [];
		if (component.services) {
			for (const serviceName of component.services) {
				const loadedService = await loadService(serviceName);
				if (loadedService) {
					loadedServices.push(loadedService);
				}
			}
		}
		return loadedServices;
	}
</script>

<div class="grid w-full h-full" style="display: grid; {componentsData.layout || ''}">
	{#each componentsData.children as component (component.id)}
		{#await Promise.all( [getComponent(component.componentName), getServiceProps(component)] ) then [Component, serviceProps]}
			{#if Component}
				<div class="w-full h-full overflow-hidden {component.slot}">
					<svelte:component
						this={Component}
						id={component.id}
						{...component.props}
						{...serviceProps.reduce((acc, currServiceModule, idx) => {
							acc[component.services[idx]] = currServiceModule;
							return acc;
						}, {})}
					/>

					{#if component.actions}
						<div class="flex justify-end p-4">
							{#each component.actions as action}
								{#await getComponent(action) then ActionComponent}
									{#if ActionComponent}
										<svelte:component this={ActionComponent} {...component.props} />
									{:else}
										<p>Action {action} not found.</p>
									{/if}
								{/await}
							{/each}
						</div>
					{/if}

					{#if component.children && component.children.length}
						<Composite componentsData={component} />
					{/if}
				</div>
			{:else}
				<p>Component {component.componentName} not found.</p>
			{/if}
		{/await}
	{/each}
</div>
