/**
 * Shared domain types used by the admin app and the frontend player.
 */

export type LayoutId = 'card' | 'hero' | 'compact' | 'button' | ( string & {} );
export type ThemeMode = 'light' | 'dark' | 'auto';

export interface Stream {
	url: string;
	label: string;
	format: '' | 'mp3' | 'aac' | 'ogg' | 'hls' | 'dash';
	bitrate: number;
}

export interface Station {
	id: number;
	name: string;
	/** Public station page (set while station pages are enabled). */
	url?: string;
	/** Links for external players (set by the frontend payload). */
	m3u?: string;
	pls?: string;
	slogan: string;
	description: string;
	genre: string;
	frequency: string;
	website: string;
	email?: string;
	phone?: string;
	logo: string;
	streams: Stream[];
	social: Record< string, string >;
	timezone?: string;
}

export interface Tokens {
	primary: string;
	accent: string;
	background: string;
	text: string;
	radius: string;
	fontFamily: string;
	/** extra CSS custom properties emitted as --ss-<key> (skin vars + user overrides). */
	vars?: Record< string, string >;
}

/** per-device component visibility overrides, e.g. { mobile: { social: false } }. */
export type DeviceId = 'desktop' | 'tablet' | 'mobile';
export type Visibility = Partial<
	Record< DeviceId, Partial< Record< keyof Components, boolean > > >
>;

/** a template is a partial config merged over the defaults. */
export interface TemplateDef {
	id: string;
	label: string;
	description: string;
	config: Partial< PlayerConfig >;
}

/** a saved style preset (skin + theme + tokens, add-on appearance extras). */
export interface StylePreset {
	id: string;
	label: string;
	skin: string;
	theme: ThemeMode;
	tokens: Tokens;
	/** Add-on config branches (see appearance.registerConfigBranch). */
	[ branch: string ]: unknown;
}

export interface Components {
	logo: boolean;
	stationName: boolean;
	slogan: boolean;
	nowPlaying: boolean;
	artwork: boolean;
	liveBadge: boolean;
	volume: boolean;
	stationSwitcher: boolean;
	listeners: boolean;
	/** Components added by add-ons (registered through the `streamsera_components` filter). */
	[ key: string ]: boolean | undefined;
}

export interface Behavior {
	autoplay: boolean;
	/** When autoplay is blocked, start muted and show an "unmute" prompt instead of waiting. */
	autoplayMuted?: boolean;
	metadataInterval: number;
	liveText: string;
	switcherStyle: 'dropdown' | 'tabs' | 'list';
	/** Keys add-ons add (see `streamsera_default_player_config`). */
	[ key: string ]: any;
}

export interface PlayerConfig {
	version: number;
	id?: number;
	station: number;
	stations: number[];
	layout: LayoutId;
	skin: string;
	theme: ThemeMode;
	tokens: Tokens;
	components: Components;
	behavior: Behavior;
	/** per-device component visibility. */
	visibility?: Visibility;
	[ key: string ]: unknown;
}

/** A recently played track (filled by add-ons that keep a history). */
export interface RecentTrack {
	title: string;
	artist: string;
	raw: string;
	artwork: string;
	time: number;
	station?: number;
	station_name?: string;
}

export interface NowPlaying {
	station: number;
	title: string;
	artist: string;
	raw: string;
	artwork: string;
	listeners: number | null;
	live: boolean;
	server: string;
	recent: RecentTrack[];
	updated: number;
	ttl: number;
	cached?: boolean;
	stale?: boolean;
	/** Live DJ / streamer name (when the provider reports one). */
	dj?: string;
	/** Overrides the live badge label when set (DJ name, current show). */
	badge?: string;
	/** Up-next track when the automation exposes it. */
	next?: { title: string; artist: string } | null;
	/** Buy / stream links for the current track. */
	links?: Array< { id: string; label: string; url: string } >;
	/** Station-level live status override (Stations → Live status card). */
	override?: 'live' | 'offair' | '';
	/** Message set with the override (e.g. "Back at 6 pm — technical difficulties"). */
	message?: string;
	/** Fields add-ons attach to the payload (`streamsera_now_playing` filter). */
	[ key: string ]: any;
}

export interface ProviderField {
	key: string;
	label: string;
	type?: 'text' | 'password' | 'url' | 'select' | 'textarea';
	help?: string;
	placeholder?: string;
	options?: Array< { label: string; value: string } >;
}

export interface ProviderDef {
	id: string;
	label: string;
	description?: string;
	/** Extra per-station inputs stored in _streamsera_metadata.fields. */
	fields?: ProviderField[];
	/** Whether the generic Status URL / Mount inputs apply. */
	usesUrl?: boolean;
	usesMount?: boolean;
	/** REST path (relative to restUrl) to POST the metadata settings to for a live test. */
	testPath?: string;
}

export type EngineState =
	| 'idle'
	| 'loading'
	| 'playing'
	| 'reconnecting'
	| 'error';

export interface Engine {
	state: EngineState;
	error: string;
	isPlaying: boolean;
	isBusy: boolean;
	play: () => void;
	pause: () => void;
	toggle: () => void;
	volume: number;
	setVolume: ( v: number ) => void;
	muted: boolean;
	toggleMute: () => void;
}

export interface LayoutDef {
	label: string;
	description: string;
}

export interface SkinDef {
	label: string;
	description?: string;
	tokens: Partial< Tokens >;
	/** extra CSS vars (--ss-<key>). */
	vars?: Record< string, string >;
	/** User-imported skins. */
	custom?: boolean;
}

/** window.StreamSeraAdmin */
export interface AdminBootstrap {
	restUrl: string;
	nonce: string;
	layouts: Record< string, LayoutDef >;
	skins: Record< string, SkinDef >;
	defaults: PlayerConfig;
	whiteLabel: boolean;
	canManage: boolean;
	/** False for contributors: new stations/players are saved as drafts. */
	canPublish?: boolean;
	canEditPosts?: boolean;
	/** The Embed dialog's "Add to page" needs edit_pages. */
	canEditPages?: boolean;
	version: string;
	adminUrl: string;
	siteUrl: string;
	docsUrl: string;
	metadataProviders?: ProviderDef[];
	/** Notice ids the current user dismissed. */
	dismissedNotices?: string[];
	templates?: TemplateDef[];
	stylePresets?: StylePreset[];
	setupCompleted?: boolean;
	/** URL patterns for feeds & external outputs (station id 0 = placeholder). */
	feeds?: Record< string, string >;
}

/** window.StreamSeraConfig */
export interface FrontendBootstrap {
	restUrl: string;
	version: string;
	defaultVolume: number;
	keyboardShortcuts: boolean;
	/** Site-wide now-playing poll interval (seconds) — Settings → Now playing. */
	pollInterval?: number;
}

declare global {
	interface Window {
		StreamSeraAdmin?: AdminBootstrap;
		StreamSeraConfig?: FrontendBootstrap;
		StreamSera?: Record< string, unknown >;
		wp?: any;
	}
}
