/**
 * Client for maskinrommet intentions API.
 * Uses /api which Caddy proxies to maskinrommet (127.0.0.1:3100).
 */

const BASE_URL = import.meta.env.VITE_API_URL ?? '/api';

export interface CreateNodeRequest {
	node_kind?: string;
	title?: string;
	content?: string;
	visibility?: string;
	metadata?: Record<string, unknown>;
	/** Kontekst-node (kommunikasjonsnode). Gir automatisk belongs_to-edge. */
	context_id?: string;
}

export interface CreateNodeResponse {
	node_id: string;
	/** Edge-ID for automatisk belongs_to-edge (kun ved context_id). */
	belongs_to_edge_id?: string;
}

export interface CreateEdgeRequest {
	source_id: string;
	target_id: string;
	edge_type: string;
	metadata?: Record<string, unknown>;
	system?: boolean;
}

export interface CreateEdgeResponse {
	edge_id: string;
}

async function post<T>(accessToken: string, path: string, data: unknown): Promise<T> {
	const res = await fetch(`${BASE_URL}${path}`, {
		method: 'POST',
		headers: {
			'Content-Type': 'application/json',
			Authorization: `Bearer ${accessToken}`
		},
		body: JSON.stringify(data)
	});

	if (!res.ok) {
		const body = await res.text();
		throw new Error(`${path} failed (${res.status}): ${body}`);
	}

	return res.json();
}

export function createNode(
	accessToken: string,
	data: CreateNodeRequest
): Promise<CreateNodeResponse> {
	return post(accessToken, '/intentions/create_node', data);
}

export function createEdge(
	accessToken: string,
	data: CreateEdgeRequest
): Promise<CreateEdgeResponse> {
	return post(accessToken, '/intentions/create_edge', data);
}

// =============================================================================
// Node-oppdatering
// =============================================================================

export interface UpdateNodeRequest {
	node_id: string;
	node_kind?: string;
	title?: string;
	content?: string;
	visibility?: string;
	metadata?: Record<string, unknown>;
}

export interface UpdateNodeResponse {
	node_id: string;
}

export function updateNode(
	accessToken: string,
	data: UpdateNodeRequest
): Promise<UpdateNodeResponse> {
	return post(accessToken, '/intentions/update_node', data);
}

// =============================================================================
// Edge-oppdatering
// =============================================================================

export interface UpdateEdgeRequest {
	edge_id: string;
	edge_type?: string;
	metadata?: Record<string, unknown>;
}

export interface UpdateEdgeResponse {
	edge_id: string;
}

export function updateEdge(
	accessToken: string,
	data: UpdateEdgeRequest
): Promise<UpdateEdgeResponse> {
	return post(accessToken, '/intentions/update_edge', data);
}

// =============================================================================
// Edge-sletting (avpublisering m.m.)
// =============================================================================

export interface DeleteEdgeRequest {
	edge_id: string;
}

export interface DeleteEdgeResponse {
	deleted: boolean;
}

export function deleteEdge(
	accessToken: string,
	data: DeleteEdgeRequest
): Promise<DeleteEdgeResponse> {
	return post(accessToken, '/intentions/delete_edge', data);
}

// =============================================================================
// Board / Kanban
// =============================================================================

export interface BoardCard {
	node_id: string;
	title: string | null;
	content: string | null;
	node_kind: string;
	metadata: Record<string, unknown>;
	created_at: string;
	created_by: string | null;
	status: string | null;
	position: number;
	belongs_to_edge_id: string;
	status_edge_id: string | null;
}

export interface BoardResponse {
	board_id: string;
	board_title: string | null;
	columns: string[];
	cards: BoardCard[];
}

export async function fetchBoard(accessToken: string, boardId: string): Promise<BoardResponse> {
	const res = await fetch(`${BASE_URL}/query/board?board_id=${encodeURIComponent(boardId)}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`board failed (${res.status}): ${body}`);
	}
	return res.json();
}

// =============================================================================
// Redaksjonell arbeidsflate (Editorial Board)
// =============================================================================

export interface EditorialCard {
	node_id: string;
	title: string | null;
	content: string | null;
	node_kind: string;
	metadata: Record<string, unknown>;
	created_at: string;
	created_by: string | null;
	author_name: string | null;
	status: string;
	submitted_to_edge_id: string;
	edge_metadata: Record<string, unknown>;
	/** Kommunikasjonsnoder knyttet til artikkelen (redaksjonelle samtaler) */
	discussion_ids: string[];
}

export interface EditorialBoardResponse {
	collection_id: string;
	collection_title: string | null;
	columns: string[];
	column_labels: Record<string, string>;
	cards: EditorialCard[];
}

export async function fetchEditorialBoard(
	accessToken: string,
	collectionId: string
): Promise<EditorialBoardResponse> {
	const res = await fetch(
		`${BASE_URL}/query/editorial_board?collection_id=${encodeURIComponent(collectionId)}`,
		{ headers: { Authorization: `Bearer ${accessToken}` } }
	);
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`editorial_board failed (${res.status}): ${body}`);
	}
	return res.json();
}

// =============================================================================
// Kommunikasjon
// =============================================================================

export interface CreateCommunicationRequest {
	title?: string;
	participants?: string[];
	visibility?: string;
	metadata?: Record<string, unknown>;
	/** Kontekst-node (f.eks. artikkel). Gir automatisk belongs_to-edge. */
	context_id?: string;
}

export interface CreateCommunicationResponse {
	node_id: string;
	edge_ids: string[];
}

export function createCommunication(
	accessToken: string,
	data: CreateCommunicationRequest
): Promise<CreateCommunicationResponse> {
	return post(accessToken, '/intentions/create_communication', data);
}

export interface UploadMediaRequest {
	file: File;
	source_id?: string;
	visibility?: string;
	title?: string;
	/** Ekstra metadata som merges inn i media-nodens metadata (f.eks. { source: "screenshot" }) */
	metadata_extra?: Record<string, unknown>;
}

export interface UploadMediaResponse {
	media_node_id: string;
	cas_hash: string;
	size_bytes: number;
	already_existed: boolean;
	has_media_edge_id?: string;
}

export async function uploadMedia(
	accessToken: string,
	data: UploadMediaRequest
): Promise<UploadMediaResponse> {
	const form = new FormData();
	form.append('file', data.file);
	if (data.source_id) form.append('source_id', data.source_id);
	if (data.visibility) form.append('visibility', data.visibility);
	if (data.title) form.append('title', data.title);
	if (data.metadata_extra) form.append('metadata_extra', JSON.stringify(data.metadata_extra));

	const res = await fetch(`${BASE_URL}/intentions/upload_media`, {
		method: 'POST',
		headers: { Authorization: `Bearer ${accessToken}` },
		body: form
	});

	if (!res.ok) {
		const body = await res.text();
		throw new Error(`upload_media failed (${res.status}): ${body}`);
	}

	return res.json();
}

/** Build the CAS URL for a given hash. */
export function casUrl(hash: string): string {
	return `${BASE_URL}/cas/${hash}`;
}

// =============================================================================
// Transkripsjons-segmenter
// =============================================================================

export interface Segment {
	id: number;
	seq: number;
	start_ms: number;
	end_ms: number;
	content: string;
	edited: boolean;
}

export interface SegmentsResponse {
	segments: Segment[];
	transcribed_at: string | null;
}

/** Hent transkripsjons-segmenter for en media-node. */
export async function fetchSegments(
	accessToken: string,
	nodeId: string
): Promise<SegmentsResponse> {
	const res = await fetch(`${BASE_URL}/query/segments?node_id=${encodeURIComponent(nodeId)}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});

	if (!res.ok) {
		const body = await res.text();
		throw new Error(`segments failed (${res.status}): ${body}`);
	}

	return res.json();
}

/** Last ned SRT-fil for en media-node. Trigger filnedlasting i nettleseren. */
export async function downloadSrt(accessToken: string, nodeId: string): Promise<void> {
	const res = await fetch(
		`${BASE_URL}/query/segments/srt?node_id=${encodeURIComponent(nodeId)}`,
		{ headers: { Authorization: `Bearer ${accessToken}` } }
	);
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`SRT-eksport feilet (${res.status}): ${body}`);
	}
	const blob = await res.blob();
	const url = URL.createObjectURL(blob);
	const a = document.createElement('a');
	a.href = url;
	a.download = 'transcription.srt';
	a.click();
	URL.revokeObjectURL(url);
}

/** Oppdater teksten i et transkripsjons-segment. */
export function updateSegment(
	accessToken: string,
	segmentId: number,
	content: string
): Promise<{ segment_id: number; edited: boolean }> {
	return post(accessToken, '/intentions/update_segment', {
		segment_id: segmentId,
		content
	});
}

// =============================================================================
// Re-transkripsjon
// =============================================================================

export interface TranscriptionVersion {
	transcribed_at: string;
	segment_count: number;
	edited_count: number;
}

export interface TranscriptionVersionsResponse {
	versions: TranscriptionVersion[];
}

/** Hent alle transkripsjonsversjoner for en node. */
export async function fetchTranscriptionVersions(
	accessToken: string,
	nodeId: string
): Promise<TranscriptionVersionsResponse> {
	const res = await fetch(
		`${BASE_URL}/query/transcription_versions?node_id=${encodeURIComponent(nodeId)}`,
		{ headers: { Authorization: `Bearer ${accessToken}` } }
	);
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`transcription_versions failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Hent segmenter for en spesifikk transkripsjonsversjon. */
export async function fetchSegmentsVersion(
	accessToken: string,
	nodeId: string,
	transcribedAt: string
): Promise<SegmentsResponse> {
	const params = new URLSearchParams({
		node_id: nodeId,
		transcribed_at: transcribedAt
	});
	const res = await fetch(`${BASE_URL}/query/segments_version?${params}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`segments_version failed (${res.status}): ${body}`);
	}
	return res.json();
}

// =============================================================================
// Graf / Kunnskapsgraf
// =============================================================================

export interface GraphNode {
	id: string;
	node_kind: string;
	title: string | null;
	visibility: string;
	metadata: Record<string, unknown>;
	created_at: string;
}

export interface GraphEdge {
	id: string;
	source_id: string;
	target_id: string;
	edge_type: string;
	metadata: Record<string, unknown>;
}

export interface GraphResponse {
	nodes: GraphNode[];
	edges: GraphEdge[];
}

export interface FetchGraphParams {
	focusId?: string;
	depth?: number;
	edgeTypes?: string[];
	nodeKinds?: string[];
}

/** Hent graf-data for visualisering. */
export async function fetchGraph(
	accessToken: string,
	params: FetchGraphParams = {}
): Promise<GraphResponse> {
	const searchParams = new URLSearchParams();
	if (params.focusId) searchParams.set('focus_id', params.focusId);
	if (params.depth) searchParams.set('depth', String(params.depth));
	if (params.edgeTypes?.length) searchParams.set('edge_types', params.edgeTypes.join(','));
	if (params.nodeKinds?.length) searchParams.set('node_kinds', params.nodeKinds.join(','));

	const res = await fetch(`${BASE_URL}/query/graph?${searchParams}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`graph failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Trigger re-transkripsjon for en media-node. */
export function retranscribe(
	accessToken: string,
	nodeId: string
): Promise<{ job_id: string }> {
	return post(accessToken, '/intentions/retranscribe', { node_id: nodeId });
}

export interface SegmentChoice {
	seq: number;
	choice: 'new' | 'old';
}

// =============================================================================
// Lydstudio
// =============================================================================

export interface AudioInfo {
	duration_ms: number;
	sample_rate: number;
	channels: number;
	codec: string;
	format: string;
	bit_rate: number | null;
}

export interface LoudnessInfo {
	input_i: number;
	input_tp: number;
	input_lra: number;
	input_thresh: number;
}

export interface SilenceRegion {
	start_ms: number;
	end_ms: number;
	duration_ms: number;
}

export interface AnalyzeResult {
	loudness: LoudnessInfo;
	silence_regions: SilenceRegion[];
	info: AudioInfo;
}

export interface EdlOperation {
	type: string;
	[key: string]: unknown;
}

export interface EdlDocument {
	source_hash: string;
	operations: EdlOperation[];
}

/** Analyser lydfil: loudness, silence-regioner, metadata. */
export function audioAnalyze(
	accessToken: string,
	casHash: string,
	silenceThresholdDb?: number,
	silenceMinDurationMs?: number
): Promise<AnalyzeResult> {
	return post(accessToken, '/intentions/audio_analyze', {
		cas_hash: casHash,
		silence_threshold_db: silenceThresholdDb,
		silence_min_duration_ms: silenceMinDurationMs
	});
}

/** Køer audio-prosessering med EDL. Returnerer job_id. */
export function audioProcess(
	accessToken: string,
	mediaNodeId: string,
	edl: EdlDocument,
	outputFormat?: string
): Promise<{ job_id: string }> {
	return post(accessToken, '/intentions/audio_process', {
		media_node_id: mediaNodeId,
		edl,
		output_format: outputFormat
	});
}

// =============================================================================
// Publisering / Forside-slots
// =============================================================================

export interface SetSlotRequest {
	edge_id: string;
	slot: string | null;
	slot_order?: number;
	pinned?: boolean;
}

export interface SetSlotResponse {
	edge_id: string;
	displaced: string[];
}

/** Sett slot-metadata (hero/featured/strøm) på en belongs_to-edge. */
export function setSlot(
	accessToken: string,
	data: SetSlotRequest
): Promise<SetSlotResponse> {
	return post(accessToken, '/intentions/set_slot', data);
}

/** Hent metadata om lydfil (ffprobe). */
export async function audioInfo(accessToken: string, hash: string): Promise<AudioInfo> {
	const res = await fetch(`${BASE_URL}/query/audio_info?hash=${encodeURIComponent(hash)}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`audio_info failed (${res.status}): ${body}`);
	}
	return res.json();
}

// =============================================================================
// Presentasjonselementer
// =============================================================================

export interface PresentationElement {
	node_id: string;
	edge_id: string;
	element_type: string;
	title: string | null;
	content: string | null;
	node_kind: string;
	metadata: Record<string, unknown>;
	edge_metadata: Record<string, unknown>;
	created_at: string;
}

export interface PresentationElementsResponse {
	article_id: string;
	elements: PresentationElement[];
}

/** Hent presentasjonselementer (tittel, undertittel, ingress, OG-bilde) for en artikkel. */
export async function fetchPresentationElements(
	accessToken: string,
	articleId: string
): Promise<PresentationElementsResponse> {
	const res = await fetch(
		`${BASE_URL}/query/presentation_elements?article_id=${encodeURIComponent(articleId)}`,
		{ headers: { Authorization: `Bearer ${accessToken}` } }
	);
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`presentation_elements failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Slett en node (brukes for å fjerne presentasjonselementer). */
export function deleteNode(
	accessToken: string,
	nodeId: string
): Promise<{ deleted: boolean }> {
	return post(accessToken, '/intentions/delete_node', { node_id: nodeId });
}

// =============================================================================
// Systemvarsler (oppgave 15.1)
// =============================================================================

export interface CreateAnnouncementRequest {
	title: string;
	content: string;
	announcement_type: 'info' | 'warning' | 'critical';
	scheduled_at?: string;
	expires_at?: string;
	blocks_new_sessions?: boolean;
}

export interface CreateAnnouncementResponse {
	node_id: string;
}

/** Opprett et systemvarsel (vises for alle klienter umiddelbart via WebSocket). */
export function createAnnouncement(
	accessToken: string,
	data: CreateAnnouncementRequest
): Promise<CreateAnnouncementResponse> {
	return post(accessToken, '/intentions/create_announcement', data);
}

export interface ExpireAnnouncementRequest {
	node_id: string;
}

export interface ExpireAnnouncementResponse {
	expired: boolean;
}

/** Fjern/utløp et systemvarsel. */
export function expireAnnouncement(
	accessToken: string,
	data: ExpireAnnouncementRequest
): Promise<ExpireAnnouncementResponse> {
	return post(accessToken, '/intentions/expire_announcement', data);
}

/** Anvend brukerens per-segment-valg etter re-transkripsjon. */
export function resolveRetranscription(
	accessToken: string,
	nodeId: string,
	newVersion: string,
	oldVersion: string,
	choices: SegmentChoice[]
): Promise<{ resolved: boolean; kept_old: number; kept_new: number }> {
	return post(accessToken, '/intentions/resolve_retranscription', {
		node_id: nodeId,
		new_version: newVersion,
		old_version: oldVersion,
		choices
	});
}

// =============================================================================
// Vedlikeholdsmodus (oppgave 15.2)
// =============================================================================

export interface RunningJob {
	id: string;
	job_type: string;
	started_at: string | null;
	collection_node_id: string | null;
}

export interface MaintenanceStatus {
	initiated: boolean;
	active: boolean;
	scheduled_at: string | null;
	announcement_node_id: string | null;
	initiated_by: string | null;
	running_jobs: RunningJob[];
}

/** Hent vedlikeholdsstatus (aktive sesjoner, kjørende jobber). */
export async function fetchMaintenanceStatus(accessToken: string): Promise<MaintenanceStatus> {
	const res = await fetch(`${BASE_URL}/admin/maintenance_status`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`maintenance_status failed (${res.status}): ${body}`);
	}
	return res.json();
}

export interface InitiateMaintenanceRequest {
	scheduled_at: string;
}

export interface InitiateMaintenanceResponse {
	announcement_node_id: string;
	scheduled_at: string;
}

/** Initier planlagt vedlikehold med nedtelling. */
export function initiateMaintenance(
	accessToken: string,
	data: InitiateMaintenanceRequest
): Promise<InitiateMaintenanceResponse> {
	return post(accessToken, '/intentions/initiate_maintenance', data);
}

/** Avbryt planlagt vedlikehold. */
export function cancelMaintenance(
	accessToken: string
): Promise<{ cancelled: boolean }> {
	return post(accessToken, '/intentions/cancel_maintenance', {});
}

// =============================================================================
// Jobbkø-oversikt (oppgave 15.3)
// =============================================================================

export interface JobDetail {
	id: string;
	collection_node_id: string | null;
	job_type: string;
	payload: Record<string, unknown>;
	status: string;
	priority: number;
	result: Record<string, unknown> | null;
	error_msg: string | null;
	attempts: number;
	max_attempts: number;
	created_at: string;
	started_at: string | null;
	completed_at: string | null;
	scheduled_for: string;
}

export interface JobCountByStatus {
	status: string;
	count: number;
}

export interface ListJobsResponse {
	jobs: JobDetail[];
	counts: JobCountByStatus[];
	job_types: string[];
}

export interface ListJobsParams {
	status?: string;
	type?: string;
	collection_id?: string;
	limit?: number;
	offset?: number;
}

/** Hent jobbliste med valgfrie filtre. */
export async function fetchJobs(
	accessToken: string,
	params: ListJobsParams = {}
): Promise<ListJobsResponse> {
	const searchParams = new URLSearchParams();
	if (params.status) searchParams.set('status', params.status);
	if (params.type) searchParams.set('type', params.type);
	if (params.collection_id) searchParams.set('collection_id', params.collection_id);
	if (params.limit) searchParams.set('limit', String(params.limit));
	if (params.offset) searchParams.set('offset', String(params.offset));

	const qs = searchParams.toString();
	const url = `${BASE_URL}/admin/jobs${qs ? `?${qs}` : ''}`;

	const res = await fetch(url, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`jobs failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Sett en feilet jobb tilbake til pending for nytt forsøk. */
export function retryJob(
	accessToken: string,
	jobId: string
): Promise<{ success: boolean }> {
	return post(accessToken, '/intentions/retry_job', { job_id: jobId });
}

/** Avbryt en ventende jobb. */
export function cancelJob(
	accessToken: string,
	jobId: string
): Promise<{ success: boolean }> {
	return post(accessToken, '/intentions/cancel_job', { job_id: jobId });
}

// =============================================================================
// AI Gateway-konfigurasjon (oppgave 15.4)
// =============================================================================

export interface AiModelAlias {
	id: string;
	alias: string;
	description: string | null;
	is_active: boolean;
	created_at: string;
}

export interface AiModelProvider {
	id: string;
	alias_id: string;
	provider: string;
	model: string;
	api_key_env: string;
	priority: number;
	is_active: boolean;
}

export interface AiJobRouting {
	job_type: string;
	alias: string;
	description: string | null;
}

export interface AiUsageSummary {
	collection_node_id: string | null;
	collection_title: string | null;
	model_alias: string;
	job_type: string | null;
	total_prompt_tokens: number;
	total_completion_tokens: number;
	total_tokens: number;
	estimated_cost: number;
	call_count: number;
}

export interface ApiKeyStatus {
	env_var: string;
	is_set: boolean;
}

export interface AiOverviewResponse {
	aliases: AiModelAlias[];
	providers: AiModelProvider[];
	routing: AiJobRouting[];
	usage: AiUsageSummary[];
	api_key_status: ApiKeyStatus[];
}

/** Hent AI Gateway-oversikt (aliaser, providers, ruting, forbruk). */
export async function fetchAiOverview(accessToken: string): Promise<AiOverviewResponse> {
	const res = await fetch(`${BASE_URL}/admin/ai`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`ai overview failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Hent AI-forbruksoversikt med filtre. */
export async function fetchAiUsage(
	accessToken: string,
	params: { days?: number; collection_id?: string } = {}
): Promise<AiUsageSummary[]> {
	const sp = new URLSearchParams();
	if (params.days) sp.set('days', String(params.days));
	if (params.collection_id) sp.set('collection_id', params.collection_id);
	const qs = sp.toString();
	const res = await fetch(`${BASE_URL}/admin/ai/usage${qs ? `?${qs}` : ''}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`ai usage failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Oppdater modellalias (beskrivelse, aktiv-status). */
export function updateAiAlias(
	accessToken: string,
	data: { id: string; description: string | null; is_active: boolean }
): Promise<{ success: boolean }> {
	return post(accessToken, '/admin/ai/update_alias', data);
}

/** Opprett nytt modellalias. */
export function createAiAlias(
	accessToken: string,
	data: { alias: string; description: string | null }
): Promise<{ id: string; success: boolean }> {
	return post(accessToken, '/admin/ai/create_alias', data);
}

/** Oppdater provider (prioritet, aktiv-status). */
export function updateAiProvider(
	accessToken: string,
	data: { id: string; priority?: number; is_active?: boolean }
): Promise<{ success: boolean }> {
	return post(accessToken, '/admin/ai/update_provider', data);
}

/** Legg til ny provider på et alias. */
export function createAiProvider(
	accessToken: string,
	data: { alias_id: string; provider: string; model: string; api_key_env: string; priority: number }
): Promise<{ id: string; success: boolean }> {
	return post(accessToken, '/admin/ai/create_provider', data);
}

/** Slett en provider. */
export function deleteAiProvider(
	accessToken: string,
	id: string
): Promise<{ success: boolean }> {
	return post(accessToken, '/admin/ai/delete_provider', { id });
}

/** Oppdater eller opprett rutingregel (jobbtype → alias). */
export function updateAiRouting(
	accessToken: string,
	data: { job_type: string; alias: string; description: string | null }
): Promise<{ success: boolean }> {
	return post(accessToken, '/admin/ai/update_routing', data);
}

/** Slett en rutingregel. */
export function deleteAiRouting(
	accessToken: string,
	jobType: string
): Promise<{ success: boolean }> {
	return post(accessToken, '/admin/ai/delete_routing', { job_type: jobType });
}

/** Test-prompt respons. */
export interface AiTestPromptResponse {
	success: boolean;
	response_text: string;
	model_used: string | null;
	prompt_tokens: number;
	completion_tokens: number;
	latency_ms: number;
	estimated_cost: number;
}

/** Send test-prompt til et alias. */
export function testAiPrompt(
	accessToken: string,
	alias: string
): Promise<AiTestPromptResponse> {
	return post(accessToken, '/admin/ai/test_prompt', { alias });
}

/** Kostnadsinfo per provider. */
export interface ProviderCostInfo {
	model: string;
	provider: string;
	priority: number;
	input_cost_per_mtok: number;
	output_cost_per_mtok: number;
	estimated_cost_1k_tokens: number;
}

/** Kostnadsinfo per tier. */
export interface TierCostInfo {
	alias: string;
	description: string | null;
	providers: ProviderCostInfo[];
}

/** Hent kostnadsestimat per tier. */
export async function fetchAiTierCosts(accessToken: string): Promise<TierCostInfo[]> {
	const res = await fetch(`${BASE_URL}/admin/ai/tier_costs`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`tier costs failed (${res.status}): ${body}`);
	}
	return res.json();
}

// =============================================================================
// Serverhelse-dashboard (oppgave 15.6)
// =============================================================================

export interface ServiceStatus {
	name: string;
	status: 'up' | 'down' | 'degraded';
	latency_ms: number | null;
	details: string | null;
}

export interface SystemMetrics {
	cpu_usage_percent: number;
	cpu_cores: number;
	load_avg: [number, number, number];
	memory_total_bytes: number;
	memory_used_bytes: number;
	memory_available_bytes: number;
	memory_usage_percent: number;
	disk: {
		mount_point: string;
		total_bytes: number;
		used_bytes: number;
		available_bytes: number;
		usage_percent: number;
		alert_level: string | null;
	};
	uptime_seconds: number;
}

export interface BackupInfo {
	backup_type: string;
	last_success: string | null;
	path: string | null;
	status: 'ok' | 'missing' | 'stale';
}

export interface PgStats {
	active_connections: number;
	max_connections: number;
	database_size_bytes: number;
	active_queries: number;
}

export interface HealthDashboard {
	services: ServiceStatus[];
	metrics: SystemMetrics;
	backups: BackupInfo[];
	pg_stats: PgStats;
}

export interface LogEntry {
	timestamp: string;
	service: string;
	level: string;
	message: string;
}

export interface LogsResponse {
	entries: LogEntry[];
}

/** Hent komplett serverhelse-dashboard. */
export async function fetchHealthDashboard(accessToken: string): Promise<HealthDashboard> {
	const res = await fetch(`${BASE_URL}/admin/health`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`health dashboard failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Hent logger for en tjeneste (eller alle). */
export async function fetchHealthLogs(
	accessToken: string,
	params: { service?: string; lines?: number } = {}
): Promise<LogsResponse> {
	const qs = new URLSearchParams();
	if (params.service) qs.set('service', params.service);
	if (params.lines) qs.set('lines', String(params.lines));
	const query = qs.toString();
	const res = await fetch(`${BASE_URL}/admin/health/logs${query ? `?${query}` : ''}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`health logs failed (${res.status}): ${body}`);
	}
	return res.json();
}

// =============================================================================
// Forbruksoversikt (oppgave 15.8)
// =============================================================================

export interface CollectionUsageSummary {
	collection_id: string | null;
	collection_title: string | null;
	resource_type: string;
	event_count: number;
	total_value: number;
	secondary_value: number;
}

export interface AiDrillDown {
	collection_id: string | null;
	collection_title: string | null;
	job_type: string | null;
	model_level: string | null;
	tokens_in: number;
	tokens_out: number;
	event_count: number;
}

export interface DailyUsage {
	day: string;
	resource_type: string;
	event_count: number;
	total_value: number;
}

export interface UsageOverviewResponse {
	by_collection: CollectionUsageSummary[];
	ai_drilldown: AiDrillDown[];
	daily: DailyUsage[];
}

/** Hent aggregert forbruksoversikt for admin. */
export async function fetchUsageOverview(
	accessToken: string,
	params: { days?: number; collection_id?: string } = {}
): Promise<UsageOverviewResponse> {
	const sp = new URLSearchParams();
	if (params.days) sp.set('days', String(params.days));
	if (params.collection_id) sp.set('collection_id', params.collection_id);
	const qs = sp.toString();
	const res = await fetch(`${BASE_URL}/admin/usage${qs ? `?${qs}` : ''}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`usage overview failed (${res.status}): ${body}`);
	}
	return res.json();
}

// ============================================================================
// Brukersynlig forbruk (oppgave 15.9)
// ============================================================================

export interface ResourceTypeSummary {
	resource_type: string;
	event_count: number;
	total_value: number;
	secondary_value: number;
}

export interface UserDailyUsage {
	day: string;
	resource_type: string;
	event_count: number;
	total_value: number;
}

export interface GraphStats {
	nodes_created: number;
	edges_created: number;
}

export interface UserUsageResponse {
	by_type: ResourceTypeSummary[];
	daily: UserDailyUsage[];
	graph: GraphStats;
}

export interface NodeUsageResponse {
	node_id: string;
	node_title: string | null;
	by_type: ResourceTypeSummary[];
	daily: UserDailyUsage[];
}

/** Hent innlogget brukers eget ressursforbruk. */
export async function fetchMyUsage(
	accessToken: string,
	params: { days?: number } = {}
): Promise<UserUsageResponse> {
	const sp = new URLSearchParams();
	if (params.days) sp.set('days', String(params.days));
	const qs = sp.toString();
	const res = await fetch(`${BASE_URL}/my/usage${qs ? `?${qs}` : ''}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`my usage failed (${res.status}): ${body}`);
	}
	return res.json();
}

// =============================================================================
// LiveKit / Kommunikasjonsrom (oppgave 16.1)
// =============================================================================

export interface JoinCommunicationRequest {
	communication_id: string;
	role?: 'publisher' | 'subscriber';
}

export interface RoomParticipantInfo {
	user_id: string;
	display_name: string;
	role: string;
}

export interface JoinCommunicationResponse {
	livekit_room_name: string;
	livekit_token: string;
	livekit_url: string;
	identity: string;
	participants: RoomParticipantInfo[];
}

export interface LeaveCommunicationResponse {
	status: string;
}

/** Bli med i et LiveKit-rom for en kommunikasjonsnode. */
export function joinCommunication(
	accessToken: string,
	data: JoinCommunicationRequest
): Promise<JoinCommunicationResponse> {
	return post(accessToken, '/intentions/join_communication', data);
}

/** Forlat et LiveKit-rom. */
export function leaveCommunication(
	accessToken: string,
	communicationId: string
): Promise<LeaveCommunicationResponse> {
	return post(accessToken, '/intentions/leave_communication', {
		communication_id: communicationId
	});
}

// =============================================================================
// AI-prosessering
// =============================================================================

export interface AiProcessRequest {
	source_node_id: string;
	ai_preset_id: string;
	direction: 'node_to_tool' | 'tool_to_node';
}

export interface AiProcessResponse {
	job_id: string;
}

export function aiProcess(
	accessToken: string,
	data: AiProcessRequest
): Promise<AiProcessResponse> {
	return post(accessToken, '/intentions/ai_process', data);
}

// =============================================================================
// Egendefinerte AI-presets (oppgave 18.6)
// =============================================================================

export interface CreateAiPresetRequest {
	title: string;
	prompt: string;
	default_direction: 'node_to_tool' | 'tool_to_node' | 'both';
	icon: string;
	color: string;
	share_with_collection_id?: string;
}

export interface CreateAiPresetResponse {
	node_id: string;
	shared_edge_id?: string;
}

/** Opprett en egendefinert AI-preset (custom, model_profile=flash). */
export function createAiPreset(
	accessToken: string,
	data: CreateAiPresetRequest
): Promise<CreateAiPresetResponse> {
	return post(accessToken, '/intentions/create_ai_preset', data);
}

// =============================================================================
// Personlig arbeidsflate (oppgave 19.6)
// =============================================================================

export interface WorkspaceResponse {
	node_id: string;
	title: string;
	metadata: Record<string, unknown>;
	created: boolean;
}

/** Hent (eller opprett) brukerens personlige workspace. */
export async function fetchMyWorkspace(accessToken: string): Promise<WorkspaceResponse> {
	const res = await fetch(`${BASE_URL}/my/workspace`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`workspace failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Hent ressursforbruk for en spesifikk node (kun eier). */
export async function fetchNodeUsage(
	accessToken: string,
	nodeId: string,
	params: { days?: number } = {}
): Promise<NodeUsageResponse> {
	const sp = new URLSearchParams();
	sp.set('node_id', nodeId);
	if (params.days) sp.set('days', String(params.days));
	const res = await fetch(`${BASE_URL}/query/node_usage?${sp.toString()}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`node usage failed (${res.status}): ${body}`);
	}
	return res.json();
}

// =============================================================================
// Mixer-kanaler
// =============================================================================

export async function createMixerChannel(
	accessToken: string,
	roomId: string,
	targetUserId: string,
): Promise<void> {
	await post(accessToken, '/intentions/create_mixer_channel', {
		room_id: roomId,
		target_user_id: targetUserId,
	});
}

export async function setMixerGain(
	accessToken: string,
	roomId: string,
	targetUserId: string,
	gain: number,
): Promise<void> {
	await post(accessToken, '/intentions/set_gain', {
		room_id: roomId,
		target_user_id: targetUserId,
		gain,
	});
}

export async function setMixerMute(
	accessToken: string,
	roomId: string,
	targetUserId: string,
	isMuted: boolean,
): Promise<void> {
	await post(accessToken, '/intentions/set_mute', {
		room_id: roomId,
		target_user_id: targetUserId,
		is_muted: isMuted,
	});
}

export async function toggleMixerEffect(
	accessToken: string,
	roomId: string,
	targetUserId: string,
	effectName: string,
): Promise<void> {
	await post(accessToken, '/intentions/toggle_effect', {
		room_id: roomId,
		target_user_id: targetUserId,
		effect_name: effectName,
	});
}

// =============================================================================
// Orkestrering (oppgave 24.6)
// =============================================================================

export interface CompileScriptResponse {
	diagnostics: Array<{
		line: number;
		severity: 'Ok' | 'Error';
		message: string;
		suggestion: string | null;
		raw_input: string;
		compiled_output: string | null;
	}>;
	compiled: {
		steps: Array<{
			step_number: number;
			binary: string;
			args: string[];
		}>;
		global_fallback: {
			binary: string;
			args: string[];
		} | null;
		technical: string;
	} | null;
}

/** Kompiler et orkestreringsscript og få diagnostikk + kompilert resultat. */
export function compileScript(
	accessToken: string,
	script: string
): Promise<CompileScriptResponse> {
	return post(accessToken, '/intentions/compile_script', { script });
}

export interface TestOrchestrationResponse {
	job_id: string;
}

/** Trigger en manuell testkjøring av en orkestrering. */
export function testOrchestration(
	accessToken: string,
	orchestrationId: string
): Promise<TestOrchestrationResponse> {
	return post(accessToken, '/intentions/test_orchestration', {
		orchestration_id: orchestrationId
	});
}

export interface OrchestrationLogEntry {
	id: string;
	job_id: string | null;
	step_number: number;
	tool_binary: string;
	args: unknown[];
	is_fallback: boolean;
	status: string;
	exit_code: number | null;
	error_msg: string | null;
	duration_ms: number | null;
	created_at: string;
}

export interface OrchestrationLogResponse {
	entries: OrchestrationLogEntry[];
}

/** Hent kjørehistorikk for en orkestrering. */
export async function fetchOrchestrationLog(
	accessToken: string,
	orchestrationId: string,
	limit?: number
): Promise<OrchestrationLogResponse> {
	const sp = new URLSearchParams({ orchestration_id: orchestrationId });
	if (limit) sp.set('limit', String(limit));
	const res = await fetch(`${BASE_URL}/query/orchestration_log?${sp}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`orchestration_log failed (${res.status}): ${body}`);
	}
	return res.json();
}

// =============================================================================
// Webhook-admin (oppgave 29.5)
// =============================================================================

export interface WebhookInfo {
	id: string;
	title: string | null;
	token: string;
	template_id: string | null;
	collection_id: string;
	collection_title: string | null;
	created_at: string;
	event_count: number;
	last_event_at: string | null;
}

export interface WebhookTemplateInfo {
	id: string;
	name: string;
	description: string;
	service: string;
}

export interface WebhookEvent {
	node_id: string;
	title: string | null;
	created_at: string;
	payload: Record<string, unknown> | null;
}

export interface WebhooksOverviewResponse {
	webhooks: WebhookInfo[];
}

export interface CreateWebhookResponse {
	webhook_id: string;
	token: string;
}

export interface RegenerateTokenResponse {
	new_token: string;
}

/** Hent alle webhooks med aktivitetsinfo. */
export async function fetchWebhooks(accessToken: string): Promise<WebhooksOverviewResponse> {
	const res = await fetch(`${BASE_URL}/admin/webhooks`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`webhooks failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Hent siste hendelser for en webhook. */
export async function fetchWebhookEvents(
	accessToken: string,
	webhookId: string,
	limit?: number
): Promise<WebhookEvent[]> {
	const sp = new URLSearchParams({ webhook_id: webhookId });
	if (limit) sp.set('limit', String(limit));
	const res = await fetch(`${BASE_URL}/admin/webhooks/events?${sp}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`webhook events failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Opprett ny webhook for en samling. */
export function createWebhook(
	accessToken: string,
	data: { title?: string; collection_id: string; template_id?: string }
): Promise<CreateWebhookResponse> {
	return post(accessToken, '/admin/webhooks/create', data);
}

/** Regenerer webhook-token. */
export function regenerateWebhookToken(
	accessToken: string,
	webhookId: string
): Promise<RegenerateTokenResponse> {
	return post(accessToken, '/admin/webhooks/regenerate_token', { webhook_id: webhookId });
}

/** Slett en webhook. */
export function deleteWebhook(
	accessToken: string,
	webhookId: string
): Promise<{ deleted: boolean }> {
	return post(accessToken, '/admin/webhooks/delete', { webhook_id: webhookId });
}

/** Hent tilgjengelige webhook-templates. */
export async function fetchWebhookTemplates(accessToken: string): Promise<WebhookTemplateInfo[]> {
	const res = await fetch(`${BASE_URL}/admin/webhooks/templates`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`webhook templates failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Sett eller fjern template på en webhook. */
export function setWebhookTemplate(
	accessToken: string,
	webhookId: string,
	templateId: string | null
): Promise<{ template_id: string | null }> {
	return post(accessToken, '/admin/webhooks/set_template', {
		webhook_id: webhookId,
		template_id: templateId
	});
}

// =============================================================================
// Agent-oversikt (oppgave 063)
// =============================================================================

export interface AgentInfo {
	node_id: string;
	agent_key: string;
	agent_type: string;
	is_active: boolean;
	config: Record<string, unknown>;
	created_at: string;
}

export interface TokenStats {
	prompt_tokens: number;
	completion_tokens: number;
	estimated_cost: number;
}

export interface AgentUsageStats {
	usage_last_hour: number;
	usage_last_24h: number;
	usage_total: number;
	tokens_last_24h: TokenStats;
}

export interface AgentCurrentJob {
	job_id: string;
	job_type: string;
	status: string;
	started_at: string | null;
	communication_id: string | null;
}

export interface AgentDetail {
	agent: AgentInfo;
	usage: AgentUsageStats;
	current_jobs: AgentCurrentJob[];
}

export interface AgentHistoryEntry {
	job_id: string;
	status: string;
	started_at: string | null;
	completed_at: string | null;
	duration_ms: number | null;
	error_msg: string | null;
	communication_id: string | null;
	result_status: string | null;
}

export interface AgentsOverviewResponse {
	agents: AgentDetail[];
	history: AgentHistoryEntry[];
}

export interface ToggleAgentResponse {
	node_id: string;
	is_active: boolean;
}

/** Hent agent-oversikt med status, forbruk og historikk. */
export async function fetchAgentsOverview(accessToken: string): Promise<AgentsOverviewResponse> {
	const res = await fetch(`${BASE_URL}/admin/agents`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`agents overview failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Aktiver/deaktiver en agent (kill switch toggle). */
export function toggleAgent(
	accessToken: string,
	nodeId: string
): Promise<ToggleAgentResponse> {
	return post(accessToken, '/admin/agents/toggle', { node_id: nodeId });
}

// =========================================================================
// Brukeradministrasjon (oppgave 064)
// =========================================================================

export interface UserRole {
	collection_id: string;
	collection_title: string;
	role: string;
}

export interface UserAiBudget {
	monthly_limit_usd: number;
}

export interface UserInfo {
	node_id: string;
	title: string;
	email: string | null;
	visibility: string;
	created_at: string;
	metadata: Record<string, unknown>;
	is_active: boolean;
	roles: UserRole[];
	ai_budget: UserAiBudget | null;
	ai_usage_this_month: number;
	last_activity: string | null;
}

export interface UsersOverviewResponse {
	users: UserInfo[];
	total_count: number;
}

export interface ToggleUserResponse {
	node_id: string;
	is_active: boolean;
}

export interface UpdateBudgetResponse {
	node_id: string;
	ai_budget: UserAiBudget | null;
}

/** Hent brukeroversikt med roller, AI-budsjett og aktivitet. */
export async function fetchUsersOverview(accessToken: string): Promise<UsersOverviewResponse> {
	const res = await fetch(`${BASE_URL}/admin/users`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`users overview failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Aktiver/deaktiver en bruker (toggle visibility). */
export function toggleUser(
	accessToken: string,
	nodeId: string
): Promise<ToggleUserResponse> {
	return post(accessToken, '/admin/users/toggle', { node_id: nodeId });
}

/** Oppdater AI-budsjett for en bruker. null fjerner budsjettet. */
export function updateUserBudget(
	accessToken: string,
	nodeId: string,
	monthlyLimitUsd: number | null
): Promise<UpdateBudgetResponse> {
	return post(accessToken, '/admin/users/budget', {
		node_id: nodeId,
		monthly_limit_usd: monthlyLimitUsd
	});
}

export async function setMixerRole(
	accessToken: string,
	roomId: string,
	targetUserId: string,
	role: string,
): Promise<void> {
	await post(accessToken, '/intentions/set_mixer_role', {
		room_id: roomId,
		target_user_id: targetUserId,
		role,
	});
}

// =========================================================================
// AI-assistert script-generering (oppgave 24.7)
// =========================================================================

export interface AiSuggestScriptRequest {
	description: string;
	trigger_event?: string;
	trigger_conditions?: Record<string, unknown>;
	eventually?: boolean;
	collection_id?: string;
}

export interface AiSuggestScriptResponse {
	status: string;
	script?: string;
	compile_result?: CompileScriptResponse;
	work_item_id?: string;
	message?: string;
}

/** AI-assistert generering av orkestreringsscript fra fritekst-beskrivelse. */
export function aiSuggestScript(
	accessToken: string,
	req: AiSuggestScriptRequest
): Promise<AiSuggestScriptResponse> {
	return post(accessToken, '/intentions/ai_suggest_script', req);
}

// =============================================================================
// Podcast-statistikk (oppgave 30.4)
// =============================================================================

export interface EpisodeTotal {
	episode_id: string | null;
	episode_title: string | null;
	total_downloads: number;
	total_unique_listeners: number;
	first_date: string | null;
	last_date: string | null;
	days_with_data: number;
}

export interface DailyDownloads {
	date: string;
	downloads: number;
	unique_listeners: number;
}

export interface ClientBreakdown {
	client: string;
	count: number;
}

export interface PodcastStatsResponse {
	total_downloads: number;
	total_unique_listeners: number;
	episodes: EpisodeTotal[];
	daily: DailyDownloads[];
	clients: ClientBreakdown[];
}

/** Hent podcast-nedlastingsstatistikk for admin. */
export async function fetchPodcastStats(
	accessToken: string,
	params: { days?: number; episode_id?: string } = {}
): Promise<PodcastStatsResponse> {
	const sp = new URLSearchParams();
	if (params.days) sp.set('days', String(params.days));
	if (params.episode_id) sp.set('episode_id', params.episode_id);
	const qs = sp.toString();
	const res = await fetch(`${BASE_URL}/admin/podcast/stats${qs ? `?${qs}` : ''}`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`podcast stats failed (${res.status}): ${body}`);
	}
	return res.json();
}

// =============================================================================
// Podcast-import wizard (oppgave 30.7)
// =============================================================================

export interface EpisodePreview {
	guid: string;
	title: string;
	published_at: string | null;
	duration: string | null;
	episode_number: number | null;
	season_number: number | null;
	action: string;
	node_id: string | null;
	error: string | null;
}

export interface ImportPreviewResponse {
	status: string;
	feed_url: string;
	feed_title: string | null;
	episodes_found: number;
	episodes_imported: number;
	episodes_skipped: number;
	dry_run: boolean;
	episodes: EpisodePreview[];
	errors: string[];
}

export interface ImportStartResponse {
	job_id: string;
}

export interface ImportStatusResponse {
	job_id: string;
	status: string;
	result: ImportPreviewResponse | null;
	error_msg: string | null;
	created_at: string;
	started_at: string | null;
	completed_at: string | null;
}

export interface PodcastCollection {
	id: string;
	title: string | null;
	slug: string | null;
}

/** Forhåndsvisning av podcast-import (dry-run). */
export function podcastImportPreview(
	accessToken: string,
	feedUrl: string,
	collectionId: string
): Promise<ImportPreviewResponse> {
	return post(accessToken, '/admin/podcast/import-preview', {
		feed_url: feedUrl,
		collection_id: collectionId
	});
}

/** Start podcast-import via jobbkø. Returnerer job_id. */
export function podcastImportStart(
	accessToken: string,
	feedUrl: string,
	collectionId: string
): Promise<ImportStartResponse> {
	return post(accessToken, '/admin/podcast/import', {
		feed_url: feedUrl,
		collection_id: collectionId
	});
}

/** Hent status for en podcast-import-jobb. */
export async function podcastImportStatus(
	accessToken: string,
	jobId: string
): Promise<ImportStatusResponse> {
	const res = await fetch(
		`${BASE_URL}/admin/podcast/import-status?job_id=${encodeURIComponent(jobId)}`,
		{ headers: { Authorization: `Bearer ${accessToken}` } }
	);
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`import status failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Hent samlinger med podcast-trait (for import-wizard dropdown). */
export async function fetchPodcastCollections(
	accessToken: string
): Promise<PodcastCollection[]> {
	const res = await fetch(`${BASE_URL}/admin/podcast/collections`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`podcast collections failed (${res.status}): ${body}`);
	}
	return res.json();
}

// =============================================================================
// API-nøkler (oppgave 060)
// =============================================================================

export interface ApiKeyInfo {
	id: string;
	provider: string;
	label: string | null;
	key_hint: string | null;
	is_active: boolean;
	created_at: string;
	updated_at: string;
	last_used: string | null;
	usage_count: number;
}

export interface ApiKeysResponse {
	keys: ApiKeyInfo[];
}

export interface TestKeyResponse {
	success: boolean;
	message: string;
}

/** Hent alle API-nøkler. */
export async function fetchApiKeys(accessToken: string): Promise<ApiKeysResponse> {
	const res = await fetch(`${BASE_URL}/admin/api-keys`, {
		headers: { Authorization: `Bearer ${accessToken}` }
	});
	if (!res.ok) {
		const body = await res.text();
		throw new Error(`api-keys failed (${res.status}): ${body}`);
	}
	return res.json();
}

/** Opprett ny API-nøkkel. */
export function createApiKey(
	accessToken: string,
	data: { provider: string; label?: string; api_key: string }
): Promise<{ id: string; key_hint: string }> {
	return post(accessToken, '/admin/api-keys/create', data);
}

/** Test API-nøkkel tilkobling. */
export function testApiKey(
	accessToken: string,
	data: { provider: string; api_key: string }
): Promise<TestKeyResponse> {
	return post(accessToken, '/admin/api-keys/test', data);
}

/** Deaktiver/aktiver API-nøkkel. */
export function deactivateApiKey(
	accessToken: string,
	id: string
): Promise<{ is_active: boolean }> {
	return post(accessToken, '/admin/api-keys/deactivate', { id });
}

/** Slett API-nøkkel permanent. */
export function deleteApiKey(
	accessToken: string,
	id: string
): Promise<{ deleted: boolean }> {
	return post(accessToken, '/admin/api-keys/delete', { id });
}
