/**
 * Provider descriptor interface.
 *
 * Each service provider type has exactly one descriptor that declares
 * everything the UI needs: config form fields, event tracking fields,
 * collection metadata, validation, and provider-specific hooks.
 *
 * Components consume descriptors via the registry (see ./index.ts)
 * instead of if/else chains keyed on provider type strings.
 */

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

// ── Config form ──────────────────────────────────────────────────────

export interface ConfigField {
	/** Form field key (flat namespace, e.g. "api_key", "nut_host"). */
	key: string;
	/** Key in the config payload sent to the API (defaults to `key`). */
	configKey?: string;
	/** i18n key for the field label. */
	label: string;
	type: 'text' | 'password' | 'number' | 'grid-select' | 'toggle';
	/** Grid-select item source function name from grid-items.ts. */
	gridItems?: string;
	gridColumns?: number;
	placeholder?: string;
	/**
	 * - `true`  → always required
	 * - `'create-only'` → required only when creating, blank = "keep existing" on edit
	 * - `false` / omitted → optional
	 */
	required?: boolean | 'create-only';
	/** Show "(optional)" suffix next to label. */
	optional?: boolean;
	/** i18n key for hint text below the field. */
	hint?: string;
	/** Edit-mode label override (e.g. "API key (leave blank to keep)"). */
	editLabel?: string;
	min?: number;
	max?: number;
	/** Default value for this field. */
	defaultValue?: string | number | boolean;
}

// ── Event tracking (TrackingConfig form) ─────────────────────────────

export interface EventTrackingField {
	/** Form field key, e.g. "track_assets_added". */
	key: string;
	/** i18n key for checkbox label. */
	label: string;
	/** Default value when creating a new tracking config. */
	default: boolean;
	/** Optional i18n key for a Hint tooltip. */
	hint?: string;
}

/** Extra non-boolean fields shown after event checkboxes (e.g. max_assets). */
export interface ExtraTrackingField {
	key: string;
	label: string;
	/**
	 * Control kind:
	 * - `number`       — numeric spinner
	 * - `grid-select`  — icon-grid chooser (requires `gridItems`)
	 * - `toggle`       — on/off switch
	 * - `date`         — HTML date picker (YYYY-MM-DD)
	 * - `time`         — HTML time picker (HH:MM)
	 * - `time-list`    — comma-separated HH:MM list, validated on blur
	 */
	type: 'number' | 'grid-select' | 'toggle' | 'date' | 'time' | 'time-list';
	/** Grid-select item source function name from grid-items.ts. */
	gridItems?: string;
	gridColumns?: number;
	hint?: string;
	/** Inline helper text rendered under the input (not a tooltip). */
	inlineHelp?: string;
	min?: number;
	max?: number;
	/** For time-list: show live validation + auto-normalize on blur. */
	validateFormat?: boolean;
	/**
	 * Default value. Can be a function for dynamic values (e.g. today's date)
	 * evaluated each time the form is reset.
	 */
	defaultValue?: string | number | boolean | (() => string | number | boolean);
}

/** A feature section like periodic summary, scheduled assets, memory mode. */
export interface FeatureSection {
	/** Unique key, e.g. "periodic", "scheduled", "memory". */
	key: string;
	/** i18n key for fieldset legend. */
	legend: string;
	/** Hint tooltip for legend. */
	legendHint?: string;
	/** Form field that toggles this section on/off. */
	enabledField: string;
	/** Default value for the enabled field. */
	enabledDefault: boolean;
	/** Fields shown when section is enabled. */
	fields: ExtraTrackingField[];
	/** Boolean fields (checkboxes) inside the section. */
	checkboxes?: EventTrackingField[];
}

// ── Collection metadata (TrackerForm) ────────────────────────────────

export interface CollectionMeta {
	/** i18n key for collection noun ("Albums", "Repositories", etc.). */
	label: string;
	/** MDI icon name. */
	icon: string;
	/** i18n key for multi-select placeholder. */
	placeholder: string;
	/** i18n key for count badge in tracker list (e.g. "3 albums"). */
	countLabel: string;
	/** Per-collection description line. */
	desc: (col: any) => string;
}

// ── User-identity filters (TrackerForm) ──────────────────────────────

/**
 * Declares a filter rendered on the tracker form. Two input modes:
 *
 * * ``picker`` (default) — populated from the provider's ``/users``
 *   endpoint, rendered as a ``MultiEntitySelect``. Used for sender
 *   allowlists / blocklists where the valid values are known.
 * * ``tags`` — free-text chip input. Used for glob patterns and other
 *   filter values that aren't enumerable in advance.
 *
 * Either way the picked values are stored as ``string[]`` under
 * ``tracker.filters[filterKey ?? key]``.
 */
export interface UserFilterMeta {
	/** Form field key — used internally for binding. */
	key: string;
	/**
	 * Filter key inside ``tracker.filters``. Defaults to ``key`` when
	 * omitted (backward compat with the original sender allowlist usage).
	 */
	filterKey?: string;
	/** ``picker`` (default) or ``tags`` for free-text chip input. */
	inputMode?: 'picker' | 'tags';
	/** i18n key for the label rendered above the input. */
	label: string;
	/** i18n key for the placeholder (picker dropdown or chip input). */
	placeholder: string;
	/** MDI icon shown on chips and dropdown rows. */
	icon: string;
}

// ── Main descriptor ──────────────────────────────────────────────────

export interface ProviderDescriptor {
	/** Provider type string (must match backend). */
	type: string;
	/** Default display name for new providers. */
	defaultName: string;
	/** MDI icon name. */
	icon: string;

	// ── Provider config form ──
	/** Whether this provider shows a URL field. */
	hasUrl: boolean;
	/** Placeholder for the URL field. */
	urlPlaceholder?: string;
	/** Provider-specific config fields (API key, webhook secret, etc.). */
	configFields: ConfigField[];
	/** Build the config payload from flat form state. Return error i18n key to abort. */
	buildConfig(form: Record<string, any>, editing: boolean): { config: Record<string, any>; error?: string };
	/** Detect whether any config field changed during edit (secrets are blank on load). */
	hasConfigChanged(form: Record<string, any>, existing: Record<string, any>): boolean;

	// ── Event tracking ──
	/** Checkbox fields for the "Event tracking" fieldset. */
	eventFields: EventTrackingField[];
	/** Extra non-boolean controls shown after the event checkboxes. */
	extraTrackingFields?: ExtraTrackingField[];
	/** Feature sections (periodic, scheduled, memory) — only for providers that support them. */
	featureSections?: FeatureSection[];

	// ── Collections / Trackers ──
	/** Null means this provider has no collections (e.g. scheduler). */
	collectionMeta: CollectionMeta | null;
	/** Sender allowlist / blocklist pickers shown on the tracker form. */
	userFilters?: UserFilterMeta[];
	/** Whether this provider is webhook-based (hides scan_interval). */
	webhookBased?: boolean;

	// ── Webhook URL display ──
	/** Pattern shown in edit mode, e.g. "/api/webhooks/gitea/{id}". */
	webhookUrlPattern?: string;
	/** Whether this provider stores incoming payload history for debugging. */
	payloadHistory?: boolean;

	// ── Tracker-form discovery hint ──
	/**
	 * Optional info banner shown on the TrackerForm to point users at related
	 * configuration pages they would otherwise have to discover from docs.
	 *
	 * The hint is rendered as a single i18n message followed by zero or more
	 * call-to-action links. ``ctas[].href`` may include ``{tracking_config_id}``
	 * / ``{template_config_id}`` placeholders that the form substitutes from
	 * the tracker's currently selected default-config IDs (or omits the
	 * ``?edit=...`` query when the value is 0).
	 */
	featureDiscoveryHint?: {
		messageKey: string;
		ctas?: Array<{ href: string; labelKey: string; icon?: string }>;
	};

	// ── Provider-specific hooks ──
	/**
	 * Called after collection selection changes (before save).
	 * E.g. Immich shared-link validation.
	 */
	onBeforeSave?(ctx: {
		form: Record<string, any>;
		previousCollectionIds: string[];
		collections: any[];
		api: typeof api;
	}): Promise<{ warnings?: { id: string; name: string; issue: string }[]; proceed: boolean }>;
}
