import { error } from '@sveltejs/kit';
import type { PageServerLoad } from './$types';
import {
	GetProjectStore,
	ProjectSessionByProjectStore,
	ProjectScopeStore,
	ProjectSessionPhotosStore,
	ProjectSessionVideosStore
} from '$houdini';
import type { ProjectSessionPhotos$result, ProjectSessionVideos$result } from '$houdini';
import { fromGlobalId, toGlobalId } from '$lib/utils/relay';

type SessionPhoto = ProjectSessionPhotos$result['projectSessionImages'][number];
type SessionVideo = ProjectSessionVideos$result['projectSessionVideos'][number];
import { WAVE_ACCESS_TOKEN } from '$env/static/private';
import { PUBLIC_WAVE_BUSINESS_ID } from '$env/static/public';
import { createWaveServerClient } from '$lib/graphql/wave/client';
import { GetProductsDocument, type ProductEdge, type Product } from '$lib/graphql/wave/generated';

export interface WaveProduct {
	id: string;
	name: string;
	description: string | null;
	unitPrice: number;
	isArchived: boolean;
}

async function fetchWaveProducts(): Promise<WaveProduct[]> {
	const client = createWaveServerClient(WAVE_ACCESS_TOKEN);

	const result = await client.query(GetProductsDocument, {
		businessId: PUBLIC_WAVE_BUSINESS_ID,
		pageSize: 500,
		isSold: true,
		isArchived: false
	});

	if (result.error) {
		console.error('Wave API error:', result.error);
		return [];
	}

	const edges = result.data?.business?.products?.edges ?? [];
	return edges
		.filter((edge: ProductEdge): edge is ProductEdge & { node: Product } => edge.node != null)
		.map((edge: ProductEdge & { node: Product }) => ({
			id: edge.node.id,
			name: edge.node.name,
			description: edge.node.description ?? null,
			unitPrice: edge.node.unitPrice,
			isArchived: edge.node.isArchived
		}));
}

export const load: PageServerLoad = async (event) => {
	const { params, locals, parent } = event;
	const projectId = params.project;
	const projectUuid = fromGlobalId(projectId);

	// Fetch params for Houdini stores
	const fetchParams = { event, metadata: { cookie: locals.cookie } };

	// Fetch project and Wave products in parallel (Wave is slow, start it early)
	const [projectData, waveProducts] = await Promise.all([
		new GetProjectStore().fetch({ ...fetchParams, variables: { id: projectId } }),
		fetchWaveProducts()
	]);

	const project = projectData?.data?.project;
	if (!project) {
		throw error(404, 'Project not found');
	}

	// Build parallel fetch promises based on project state
	const needsSession = project.status === 'IN_PROGRESS' || project.status === 'COMPLETED';

	// Fetch session and scope in parallel
	const [sessionResult, scopeResult] = await Promise.all([
		// Session fetch (only if needed)
		needsSession
			? new ProjectSessionByProjectStore()
					.fetch({ ...fetchParams, variables: { projectId: projectUuid } })
					.catch(() => ({ data: { projectSessions: [] } }))
			: Promise.resolve(null),
		// Scope fetch (only if has scopeId)
		project.scopeId
			? new ProjectScopeStore()
					.fetch({
						...fetchParams,
						variables: { id: toGlobalId('ProjectScopeType', project.scopeId) }
					})
					.catch(() => ({ data: { projectScope: null } }))
			: Promise.resolve(null)
	]);

	const baseSession = sessionResult?.data?.projectSessions?.[0] ?? null;
	let photos: SessionPhoto[] = [];
	let videos: SessionVideo[] = [];

	// If we have a session, fetch photos and videos in parallel
	if (baseSession) {
		const sessionUuid = fromGlobalId(baseSession.id);
		const [photosResult, videosResult] = await Promise.all([
			new ProjectSessionPhotosStore()
				.fetch({ ...fetchParams, variables: { sessionId: sessionUuid } })
				.catch((err) => {
					console.error('Failed to fetch session photos:', err);
					return { data: { projectSessionImages: [] as SessionPhoto[] } };
				}),
			new ProjectSessionVideosStore()
				.fetch({ ...fetchParams, variables: { sessionId: sessionUuid } })
				.catch((err) => {
					console.error('Failed to fetch session videos:', err);
					return { data: { projectSessionVideos: [] as SessionVideo[] } };
				})
		]);

		photos = photosResult?.data?.projectSessionImages ?? [];
		videos = videosResult?.data?.projectSessionVideos ?? [];
	}

	// Combine session with photos/videos
	const session = baseSession ? { ...baseSession, photos, videos } : null;

	// Get project scope templates from parent layout (already fetched there)
	const parentData = await parent();

	return {
		project,
		projectUuid,
		session,
		scope: scopeResult?.data?.projectScope ?? null,
		projectScopeTemplates: parentData.projectScopes,
		waveProducts
	};
};
