/**
 * Typed API client for the FastAPI backend.
 */

import type {
	MediaCounts,
	LibraryCount,
	UserDirectoryResponse,
	UserMessageResponse,
	UserMessageQueueStatus,
	NowPlayingSession,
	AppVersionInfo,
	SSHKey,
	SSHKeyInput,
	SSHKeyGenerated,
	SavedTask,
	SavedTaskInput,
	SavedTaskRun,
	MonitoringMachine,
	MonitoringMachineInput,
	MediaIndexStatus,
	MediaIndexActionResponse,
	MediaQueryResponse,
	DirectoryListing,
	JobTemplate,
	JobResult,
	ResolvedPath,
	ResetLocalDatabaseInput,
	ResetLocalDatabaseResponse,
	SSHValidationResult,
	DashboardShortcut,
	DashboardShortcutInput,
	AlertmanagerAlertSummary,
	AlertmanagerStatus,
	PrometheusStatus,
	PrometheusTarget,
} from "../types";
import {
	buildHeaders,
	buildUrl,
	del,
	get,
	post,
	postForm,
	readErrorDetail,
} from "./shared";

// Dashboard (Jellyfin-backed; selected via jellyfin_service_id)
export const fetchCounts = (jellyfinServiceId?: string) =>
	get<MediaCounts>(
		"/api/dashboard/counts",
		jellyfinServiceId ? { jellyfin_service_id: jellyfinServiceId } : undefined,
	);
export const fetchLibraries = (jellyfinServiceId?: string) =>
	get<LibraryCount[]>(
		"/api/dashboard/libraries",
		jellyfinServiceId ? { jellyfin_service_id: jellyfinServiceId } : undefined,
	);
export const fetchActivity = (jellyfinServiceId?: string) =>
	get<NowPlayingSession[]>(
		"/api/dashboard/activity",
		jellyfinServiceId ? { jellyfin_service_id: jellyfinServiceId } : undefined,
	);
export const fetchUsers = (jellyfinServiceId?: string) =>
	get<UserDirectoryResponse>(
		"/api/users",
		jellyfinServiceId ? { jellyfin_service_id: jellyfinServiceId } : undefined,
	);

// Backward-compatible alias used by older hooks/components.
export const fetchNowPlaying = fetchActivity;

// Monitoring
export const fetchMonitoringMachines = () =>
	get<MonitoringMachine[]>("/api/monitoring/machines");
export const fetchAppVersion = () => get<AppVersionInfo>("/api/version");
export const fetchDashboardShortcuts = () =>
	get<DashboardShortcut[]>("/api/dashboard/shortcuts");
export const saveDashboardShortcut = (shortcut: DashboardShortcutInput) =>
	fetch(
		buildUrl(
			shortcut.id
				? `/api/dashboard/shortcuts/${encodeURIComponent(shortcut.id)}`
				: "/api/dashboard/shortcuts",
		),
		{
			method: shortcut.id ? "PUT" : "POST",
			headers: buildHeaders(true),
			body: JSON.stringify(shortcut),
		},
	).then(async (response) => {
		if (!response.ok) {
			throw new Error(`${response.status}: ${await readErrorDetail(response)}`);
		}
		return response.json() as Promise<DashboardShortcut>;
	});
export const deleteDashboardShortcut = (shortcutId: string) =>
	del<{ status: string }>(
		`/api/dashboard/shortcuts/${encodeURIComponent(shortcutId)}`,
	);
export const fetchMonitoringSettings = () =>
	get<MonitoringMachine[]>("/api/settings/machines");
export const fetchSSHKeys = () => get<SSHKey[]>("/api/settings/ssh-keys");
export const generateSSHKey = (payload: {
	name: string;
	passphrase: string;
	notes: string;
	bits?: number;
}) => post<SSHKeyGenerated>("/api/settings/ssh-keys/generate", payload);
export const saveSSHKey = (key: SSHKeyInput) =>
	fetch(
		buildUrl(
			key.id
				? `/api/settings/ssh-keys/${encodeURIComponent(key.id)}`
				: "/api/settings/ssh-keys",
		),
		{
			method: key.id ? "PUT" : "POST",
			headers: buildHeaders(true),
			body: JSON.stringify(key),
		},
	).then(async (response) => {
		if (!response.ok) {
			throw new Error(`${response.status}: ${await readErrorDetail(response)}`);
		}
		return response.json() as Promise<SSHKey>;
	});
export const deleteSSHKey = (keyId: string) =>
	del<{ status: string }>(
		`/api/settings/ssh-keys/${encodeURIComponent(keyId)}`,
	);

export const fetchSavedTasks = () => get<SavedTask[]>("/api/tasks");
export const fetchSavedTaskRuns = (taskId: string, limit = 10) =>
	get<{ items: SavedTaskRun[]; total: number }>(
		`/api/tasks/${encodeURIComponent(taskId)}/runs`,
		{
			limit: String(limit),
		},
	);
export const saveTask = (task: SavedTaskInput) =>
	fetch(
		buildUrl(
			task.id ? `/api/tasks/${encodeURIComponent(task.id)}` : "/api/tasks",
		),
		{
			method: task.id ? "PUT" : "POST",
			headers: buildHeaders(true),
			body: JSON.stringify(task),
		},
	).then(async (response) => {
		if (!response.ok) {
			throw new Error(`${response.status}: ${await readErrorDetail(response)}`);
		}
		return response.json() as Promise<SavedTask>;
	});
export const deleteTask = (taskId: string) =>
	del<{ status: string }>(`/api/tasks/${encodeURIComponent(taskId)}`);
export const runTask = (taskId: string, serviceId?: string) =>
	post<{
		task_id: string;
		task_name: string;
		service_id: string;
		service_name: string;
		task_type: string;
		exit_status: number;
		stdout: string;
		stderr: string;
	}>(
		serviceId
			? `/api/tasks/run?service_id=${encodeURIComponent(serviceId)}`
			: "/api/tasks/run",
		{ task_id: taskId },
	);

export const saveMonitoringMachine = (machine: MonitoringMachineInput) =>
	fetch(
		buildUrl(
			machine.id
				? `/api/settings/machines/${encodeURIComponent(machine.id)}`
				: "/api/settings/machines",
		),
		{
			method: machine.id ? "PUT" : "POST",
			headers: buildHeaders(true),
			body: JSON.stringify(machine),
		},
	).then(async (response) => {
		if (!response.ok) {
			throw new Error(`${response.status}: ${await readErrorDetail(response)}`);
		}
		return response.json() as Promise<MonitoringMachine>;
	});
export const testMonitoringMachineSSH = (machine: MonitoringMachineInput) =>
	post<SSHValidationResult>("/api/settings/machines/test-ssh", machine);
export const deleteMonitoringMachine = (machineId: string) =>
	del<{ status: string }>(
		`/api/settings/machines/${encodeURIComponent(machineId)}`,
	);
export const resetLocalDatabase = (payload: ResetLocalDatabaseInput) =>
	post<ResetLocalDatabaseResponse>(
		"/api/settings/reset-local-database",
		payload,
	);

// Media
export const fetchMediaStatus = (jellyfinServiceId?: string) =>
	get<MediaIndexStatus>(
		"/api/media/status",
		jellyfinServiceId ? { jellyfin_service_id: jellyfinServiceId } : undefined,
	);
export const buildMediaIndex = (jellyfinServiceId?: string) =>
	post<MediaIndexActionResponse>(
		jellyfinServiceId
			? `/api/media/build?jellyfin_service_id=${encodeURIComponent(jellyfinServiceId)}`
			: "/api/media/build",
	);
export const stopMediaIndexBuild = (jellyfinServiceId?: string) =>
	post<MediaIndexActionResponse>(
		jellyfinServiceId
			? `/api/media/stop?jellyfin_service_id=${encodeURIComponent(jellyfinServiceId)}`
			: "/api/media/stop",
	);
export const forceStopMediaIndexBuild = (jellyfinServiceId?: string) =>
	post<MediaIndexActionResponse>(
		jellyfinServiceId
			? `/api/media/force-stop?jellyfin_service_id=${encodeURIComponent(jellyfinServiceId)}`
			: "/api/media/force-stop",
	);
export const queryMedia = (params: {
	libraries?: string;
	types?: string;
	search?: string;
	hdr_filter?: string;
	sort_key?: string;
	sort_order?: string;
	limit?: number;
	offset?: number;
	jellyfinServiceId?: string;
}) =>
	get<MediaQueryResponse>("/api/media/query", {
		libraries: params.libraries || "",
		types: params.types || "Movie,Episode",
		search: params.search || "",
		hdr_filter: params.hdr_filter || "All",
		sort_key: params.sort_key || "title",
		sort_order: params.sort_order || "Ascending",
		limit: String(params.limit || 100),
		offset: String(params.offset || 0),
		...(params.jellyfinServiceId
			? { jellyfin_service_id: params.jellyfinServiceId }
			: {}),
	});

// Files
export const fetchDirectoryListing = (path: string, machineId?: string) =>
	get<DirectoryListing>("/api/files/list", {
		path,
		...(machineId ? { machine_id: machineId } : {}),
	});
export const fetchFfprobe = (path: string, machineId?: string) =>
	get<Record<string, unknown>>("/api/files/ffprobe", {
		path,
		...(machineId ? { machine_id: machineId } : {}),
	});
export const fetchStat = (path: string, machineId?: string) =>
	get<{ path: string; output: string }>("/api/files/stat", {
		path,
		...(machineId ? { machine_id: machineId } : {}),
	});
export const resolvePath = (path: string, machineId?: string) =>
	get<ResolvedPath>("/api/files/resolve-path", {
		path,
		...(machineId ? { machine_id: machineId } : {}),
	});

// Jobs
export const fetchJobTemplates = () =>
	get<JobTemplate[]>("/api/jobs/templates");
export const runJob = (jobKey: string, path: string, machineId?: string) =>
	post<JobResult>(
		machineId
			? `/api/jobs/run?machine_id=${encodeURIComponent(machineId)}`
			: "/api/jobs/run",
		{ job_key: jobKey, path },
	);

export const fetchUserMessageQueueStatus = () =>
	get<UserMessageQueueStatus>("/api/users/message/status");

export const sendUserMessage = (formData: FormData) =>
	postForm<UserMessageResponse>("/api/users/message", formData);

// Observability summary endpoints
export const fetchAlertmanagerAlerts = () =>
	get<AlertmanagerAlertSummary>("/api/monitoring/alerts");

export const fetchAlertmanagerStatus = () =>
	get<AlertmanagerStatus>("/api/monitoring/alertmanager-status");

export const fetchPrometheusStatus = () =>
	get<PrometheusStatus>("/api/monitoring/prometheus-status");

export const fetchPrometheusTargets = () =>
	get<PrometheusTarget[]>("/api/monitoring/prometheus-targets");
