/**
 * Error reporting surface.
 *
 * Maps a classified {@link ErrorKind} to a translated, actionable message
 * and either raises it as a toast (with a Retry action for retryable
 * kinds) or hands the message key back for a view to render inline.
 */

import { toast } from "../toast.svelte";
import type { TranslationKey } from "../i18n/index.svelte";
import { classifyError, isRetryable, type ErrorKind } from "./classify";

const MESSAGE_KEY: Record<ErrorKind, TranslationKey> = {
	offline: "error.offline",
	network: "error.network",
	auth: "error.auth",
	forbidden: "error.forbidden",
	conflict: "error.conflict",
	notFound: "error.not_found",
	rateLimit: "error.rate_limit",
	server: "error.server",
	unknown: "error.unknown",
};

/** The translated message key for an error, for inline rendering. */
export function errorMessageKey(err: unknown): TranslationKey {
	return MESSAGE_KEY[classifyError(err)];
}

export interface ReportErrorOptions {
	/**
	 * Retry callback. When supplied and the error kind is retryable, the
	 * toast gains a Retry action and stays until dismissed; otherwise the
	 * toast auto-dismisses.
	 */
	onRetry?: () => void;
}

/**
 * Classify `err`, raise a translated toast, and return the kind. A
 * retryable error with an `onRetry` handler shows a sticky toast with a
 * Retry action; everything else auto-dismisses.
 */
export function reportError(
	err: unknown,
	options: ReportErrorOptions = {},
): ErrorKind {
	const kind = classifyError(err);
	const withRetry = options.onRetry !== undefined && isRetryable(kind);
	toast.show({
		messageKey: MESSAGE_KEY[kind],
		actionLabelKey: withRetry ? "common.retry" : undefined,
		onAction: withRetry ? options.onRetry : undefined,
		durationMs: withRetry ? null : 8000,
	});
	return kind;
}
