import type { components } from '$lib/generated/api';

type MonthBucket = components['schemas']['MonthBucket'];
type DocumentDensityResult = components['schemas']['DocumentDensityResult'];

export type DensityState = {
	density: MonthBucket[] | null;
	minDate: string | null;
	maxDate: string | null;
};

const SKIP: DensityState = { density: null, minDate: null, maxDate: null };
const EMPTY: DensityState = { density: [], minDate: null, maxDate: null };

/**
 * The subset of /documents URL params that should narrow the density chart.
 * Date bounds (`from`/`to`) are intentionally excluded — see
 * {@link fetchDensity} for why.
 */
export type DensityFilters = {
	q?: string;
	senderId?: string;
	receiverId?: string;
	tags?: string[];
	tagQ?: string;
	status?: string;
	tagOp?: 'AND' | 'OR';
};

/**
 * Builds the density endpoint URL, including the active non-date filters
 * so the chart matches the document list it sits above.
 */
export function buildDensityUrl(filters: DensityFilters = {}): string {
	const params = new URLSearchParams();
	if (filters.q) params.set('q', filters.q);
	if (filters.senderId) params.set('senderId', filters.senderId);
	if (filters.receiverId) params.set('receiverId', filters.receiverId);
	for (const tag of filters.tags ?? []) params.append('tag', tag);
	if (filters.tagQ) params.set('tagQ', filters.tagQ);
	if (filters.status) params.set('status', filters.status);
	if (filters.tagOp === 'OR') params.set('tagOp', 'OR');
	const qs = params.toString();
	return qs ? `/api/documents/density?${qs}` : '/api/documents/density';
}

/**
 * Loads the density data for the timeline widget. Tablet and below (lg breakpoint,
 * <1024px) and calendar view both skip the request entirely — the widget isn't
 * rendered there. A non-ok response or network failure degrades to an empty
 * bucket list instead of throwing, so the document list page keeps rendering.
 */
export async function fetchDensity(
	fetch: typeof globalThis.fetch,
	view: string | null,
	isDesktop: boolean,
	filters: DensityFilters = {}
): Promise<DensityState> {
	if (!isDesktop || view === 'calendar') return SKIP;

	try {
		const response = await fetch(buildDensityUrl(filters));
		if (!response.ok) {
			console.warn(`[timeline] density fetch responded with ${response.status}`);
			return EMPTY;
		}
		const body = (await response.json()) as DocumentDensityResult;
		return {
			density: body.buckets,
			minDate: body.minDate ?? null,
			maxDate: body.maxDate ?? null
		};
	} catch (error) {
		console.warn('[timeline] density fetch failed', error);
		return EMPTY;
	}
}
