// Path: Frontend/src/components/app-shell/data/app-shell.context.tsx

import {
	createContext,
	createMemo,
	createSignal,
	onMount,
	useContext,
	type JSX,
} from "solid-js";
import { resolveAPIBase } from "../../../lib/api";
import {
	buildActiveDepartment,
	buildActiveProject,
	buildActiveServer,
	buildActiveUserProfile,
	buildDepartmentItems,
	buildProjectItems,
	buildRailItems,
	buildWorkspaceTree,
} from "./app-shell.builders";
import type { AppShellContextValue, AppShellPayload } from "./app-shell.types";
import { normalizeAppShellPayload } from "./app-shell.types";

const AppShellContext = createContext<AppShellContextValue>();

export const AppShellDataProvider = (props: { children: JSX.Element }): JSX.Element => {
	const [status, setStatus] = createSignal<"idle" | "loading" | "success" | "error">("idle");
	const [error, setError] = createSignal("");
	const [payload, setPayload] = createSignal<AppShellPayload | null>(null);

	const load = async (): Promise<void> => {
		setStatus("loading");
		setError("");

		try {
			const response = await fetch(`${resolveAPIBase()}/app-shell`, {
				headers: {
					Accept: "application/json",
				},
			});

			const body = (await response.json()) as {
				data?: AppShellPayload;
				error?: { message?: string } | string;
				message?: string;
			};
			const errorMessage =
				typeof body.message === "string"
					? body.message
					: typeof body.error === "string"
						? body.error
						: body.error?.message;

			if (!response.ok || !body.data) {
				throw new Error(errorMessage || "Failed to load app shell state.");
			}

			setPayload(normalizeAppShellPayload(body.data));
			setStatus("success");
		} catch (loadError) {
			setStatus("error");
			setError(loadError instanceof Error ? loadError.message : "Failed to load app shell state.");
		}
	};

	onMount(() => {
		void load();
	});

	const value: AppShellContextValue = {
		status,
		error,
		installation: createMemo(() => payload()?.installation),
		railItems: createMemo(() => buildRailItems(payload())),
		activeServer: createMemo(() => buildActiveServer(payload())),
		activeProject: createMemo(() => buildActiveProject(payload())),
		activeDepartment: createMemo(() => buildActiveDepartment(payload())),
		projectItems: createMemo(() => buildProjectItems(payload())),
		departmentItems: createMemo(() => buildDepartmentItems(payload())),
		workspaceTree: createMemo(() => buildWorkspaceTree(payload())),
		activeUserProfile: createMemo(() => buildActiveUserProfile(payload())),
		reload: load,
	};

	return <AppShellContext.Provider value={value}>{props.children}</AppShellContext.Provider>;
};

export const useAppShellData = (): AppShellContextValue => {
	const context = useContext(AppShellContext);

	if (!context) {
		throw new Error("useAppShellData must be used within AppShellDataProvider");
	}

	return context;
};
