// #region EnvironmentContextStore [C:3] [TYPE Store] [SEMANTICS environment, context, store, selector, filter]
// @BRIEF Global selected environment context for navigation, safety cues, and environment-based filtering.
// @LAYER UI
// @RELATION DEPENDS_ON -> [ApiModule]
// @RELATION BINDS_TO -> [SidebarStore]
// @UX_STATE Loading -> Environments being fetched
// @UX_STATE Ready -> Environment selector active with environment list
// @UX_STATE Error -> Failed to load environments
// @RATIONALE Migrated from Svelte 4 writable/derived to Svelte 5 $state/$derived runes.
//            Backward-compatible .subscribe() retained for $environmentContextStore syntax.

import { browser } from '$app/environment';
import { api } from '$lib/api';

interface Environment {
	id: string;
	name: string;
	stage?: string;
	is_production?: boolean;
	[k: string]: unknown;
}

interface EnvironmentContextState {
	environments: Environment[];
	selectedEnvId: string;
	isLoading: boolean;
	isLoaded: boolean;
	error: string | null;
}

const INITIAL_STATE: EnvironmentContextState = {
	environments: [],
	selectedEnvId: '',
	isLoading: false,
	isLoaded: false,
	error: null,
};

const SELECTED_ENV_KEY = 'selected_env_id';

// Reactive state (Svelte 5 rune)
let _contextState: EnvironmentContextState = $state(INITIAL_STATE);

// Derived values (Svelte 5 rune)
let _selectedEnvironment: Environment | null = $derived(
	_contextState.environments.find((env) => env.id === _contextState.selectedEnvId) || null,
);

let _isProductionContext: boolean = $derived(
	String(_selectedEnvironment?.stage || '').toUpperCase() === 'PROD' ||
		Boolean(_selectedEnvironment?.is_production),
);

// Subscriber lists for backward-compatible .subscribe()
let _contextSubscribers: Array<(value: EnvironmentContextState) => void> = [];
let _selectedEnvSubscribers: Array<(value: Environment | null) => void> = [];
let _isProdSubscribers: Array<(value: boolean) => void> = [];

function _notifyContext(): void {
	const current = _contextState;
	_contextSubscribers.forEach((fn) => fn(current));
}

function _notifySelected(): void {
	const current = _selectedEnvironment;
	_selectedEnvSubscribers.forEach((fn) => fn(current));
}

function _notifyIsProd(): void {
	const current = _isProductionContext;
	_isProdSubscribers.forEach((fn) => fn(current));
}

function _notifyAll(): void {
	_notifyContext();
	_notifySelected();
	_notifyIsProd();
}

function getStoredSelectedEnvId(): string {
	if (!browser) return '';
	return localStorage.getItem(SELECTED_ENV_KEY) || '';
}

function persistSelectedEnvId(envId: string): void {
	if (!browser) return;
	if (!envId) {
		localStorage.removeItem(SELECTED_ENV_KEY);
		return;
	}
	localStorage.setItem(SELECTED_ENV_KEY, envId);
}

function hasAuthToken(): boolean {
	if (!browser) return false;
	return Boolean(localStorage.getItem('auth_token'));
}

function resolveSelectedEnvId(environments: Environment[], preferredEnvId: string): string {
	if (!Array.isArray(environments) || environments.length === 0) return '';
	if (preferredEnvId && environments.some((env) => env.id === preferredEnvId)) {
		return preferredEnvId;
	}
	const stored = getStoredSelectedEnvId();
	if (stored && environments.some((env) => env.id === stored)) {
		return stored;
	}
	return environments[0].id;
}

function applySelectedEnvId(selectedEnvId: string): void {
	const exists = _contextState.environments.some((env) => env.id === selectedEnvId);
	const nextSelectedEnvId = exists ? selectedEnvId : '';
	persistSelectedEnvId(nextSelectedEnvId);
	_contextState = { ..._contextState, selectedEnvId: nextSelectedEnvId };
	_notifyAll();
}

async function refreshEnvironmentContext(preferredEnvId: string = ''): Promise<void> {
	if (!hasAuthToken()) {
		_contextState = { ..._contextState, isLoading: false, isLoaded: false, error: null };
		_notifyAll();
		return;
	}

	_contextState = { ..._contextState, isLoading: true, error: null };
	_notifyAll();
	try {
		const environments = await api.getEnvironmentsList<Environment[]>();
		const current = _contextState.selectedEnvId;
		const selectedEnvId = resolveSelectedEnvId(environments, preferredEnvId || current);
		persistSelectedEnvId(selectedEnvId);
		_contextState = { ..._contextState, environments, selectedEnvId, isLoading: false, isLoaded: true, error: null };
		_notifyAll();
	} catch (error: unknown) {
		const apiError = error as { status?: number; message?: string };
		if (apiError?.status === 401) {
			_contextState = { ..._contextState, isLoading: false, isLoaded: false, error: null };
			_notifyAll();
			return;
		}
		console.error('[environmentContext] Failed to refresh environments', error);
		_contextState = { ..._contextState, environments: [], selectedEnvId: '', isLoading: false, isLoaded: true, error: apiError?.message || 'Failed to load environments' };
		_notifyAll();
	}
}

async function initializeEnvironmentContext(): Promise<void> {
	if (_contextState.isLoading || _contextState.isLoaded) return;
	await refreshEnvironmentContext();
}

export const environmentContextStore = {
	subscribe(run: (value: EnvironmentContextState) => void): () => void {
		_contextSubscribers.push(run);
		run(_contextState);
		return () => {
			_contextSubscribers = _contextSubscribers.filter((fn) => fn !== run);
		};
	},
	get value(): EnvironmentContextState {
		return _contextState;
	},
};

export function setSelectedEnvironment(envId: string): void {
	applySelectedEnvId(envId);
}

export { refreshEnvironmentContext, initializeEnvironmentContext };

export const selectedEnvironmentStore = {
	subscribe(run: (value: Environment | null) => void): () => void {
		_selectedEnvSubscribers.push(run);
		run(_selectedEnvironment);
		return () => {
			_selectedEnvSubscribers = _selectedEnvSubscribers.filter((fn) => fn !== run);
		};
	},
	get value(): Environment | null {
		return _selectedEnvironment;
	},
};

export const isProductionContextStore = {
	subscribe(run: (value: boolean) => void): () => void {
		_isProdSubscribers.push(run);
		run(_isProductionContext);
		return () => {
			_isProdSubscribers = _isProdSubscribers.filter((fn) => fn !== run);
		};
	},
	get value(): boolean {
		return _isProductionContext;
	},
};
// #endregion EnvironmentContextStore
