import { env } from '$env/dynamic/private';
import type { Sponsor } from '$lib/types';
import { cache } from './cache';

const SPONSORS_LOGIN = 'fatfingers23';

type SponsorNode = {
	login: string;
	name: string | null;
	avatarUrl: string;
	url: string;
};

const SPONSORS_QUERY = `
	query ($login: String!) {
		user(login: $login) {
			sponsorshipsAsMaintainer(first: 100, includePrivate: false, activeOnly: true) {
				nodes {
					sponsorEntity {
						... on User { login name avatarUrl(size: 160) url }
						... on Organization { login name avatarUrl(size: 160) url }
					}
				}
			}
		}
	}
`;

export async function fetchSponsors(fetch: typeof globalThis.fetch): Promise<Sponsor[]> {
	const cached = cache.get('sponsors');
	if (cached) {
		return cached as Sponsor[];
	}

	const token = env.GITHUB_TOKEN;
	if (!token) {
		console.warn('GITHUB_TOKEN is not set — Sponsors section will be hidden.');
		return [];
	}

	try {
		const res = await fetch('https://api.github.com/graphql', {
			method: 'POST',
			headers: {
				Authorization: `Bearer ${token}`,
				'Content-Type': 'application/json'
			},
			body: JSON.stringify({
				query: SPONSORS_QUERY,
				variables: { login: SPONSORS_LOGIN }
			})
		});

		if (!res.ok) {
			console.warn(`GitHub Sponsors request failed: ${res.status} ${res.statusText}`);
			return [];
		}

		const json = await res.json();
		if (json.errors) {
			console.warn('GitHub Sponsors GraphQL errors:', json.errors);
			return [];
		}

		const nodes: { sponsorEntity: SponsorNode | null }[] =
			json.data?.user?.sponsorshipsAsMaintainer?.nodes ?? [];
		const sponsors: Sponsor[] = nodes
			.map((node) => node.sponsorEntity)
			.filter((entity): entity is SponsorNode => Boolean(entity?.login))
			.map((entity) => ({
				login: entity.login,
				name: entity.name ?? entity.login,
				avatarUrl: entity.avatarUrl ?? `https://github.com/${entity.login}.png`,
				url: entity.url
			}));

		cache.set('sponsors', sponsors);
		return sponsors;
	} catch (error) {
		console.warn('Failed to fetch GitHub Sponsors:', error);
		return [];
	}
}
