/* eslint-disable @typescript-eslint/ban-ts-comment */
// @ts-nocheck
import { io } from 'socket.io-client';

import { api, getBackendUrl } from './api';
import { createMotionDetector } from './motion-detector';
import { getAppState, patchAppState, resetAppState, setAppState } from './store';

const PAGE_PATHS = {
	auth: '/',
	onboarding: '/onboarding',
	camera: '/camera',
	client: '/client',
	activity: '/activity',
	settings: '/settings'
};
const DEVICE_STORAGE_KEY = 'mobileSimDevice';
const INVALID_DEVICE_TOKEN_ERRORS = new Set([
	'Missing device token',
	'Invalid device token',
	'Device not found',
	'Token role does not match device role'
]);

const MOTION_DETECTION_SETTINGS_STORAGE_KEY = 'securecam-motion-detection-settings';
const MOTION_DETECTION_PROFILES = {
	low_power: {
		profile: 'low_power',
		label: 'Low Power',
		description: 'Least heat and battery usage, slower trigger response.',
		sampleIntervalMs: 1400,
		burstIntervalMs: 500,
		triggerThreshold: 0.15,
		releaseThreshold: 0.05,
		consecutiveTriggerFrames: 3,
		cooldownMs: 12000,
		minimumEventMs: 9000
	},
	balanced: {
		profile: 'balanced',
		label: 'Balanced',
		description: 'Recommended default for a plugged-in foreground browser.',
		sampleIntervalMs: 1000,
		burstIntervalMs: 300,
		triggerThreshold: 0.12,
		releaseThreshold: 0.04,
		consecutiveTriggerFrames: 3,
		cooldownMs: 9000,
		minimumEventMs: 8000
	},
	responsive: {
		profile: 'responsive',
		label: 'Responsive',
		description: 'Faster trigger response with higher CPU and thermal cost.',
		sampleIntervalMs: 700,
		burstIntervalMs: 220,
		triggerThreshold: 0.1,
		releaseThreshold: 0.035,
		consecutiveTriggerFrames: 2,
		cooldownMs: 7000,
		minimumEventMs: 7000
	}
};

const RECORDING_VIDEO_BITS_PER_SECOND = 850_000;
const COMPRESSED_UPLOAD_MAX_WIDTH = 640;
const COMPRESSED_UPLOAD_MAX_HEIGHT = 360;
const COMPRESSED_UPLOAD_FRAME_RATE = 12;
const COMPRESSED_UPLOAD_BITS_PER_SECOND = 450_000;
const DEFAULT_CAMERA_CONSTRAINTS = {
	width: { ideal: 640, max: 960 },
	height: { ideal: 360, max: 540 },
	frameRate: { ideal: 15, max: 24 }
};
const SOCKET_HEARTBEAT_INTERVAL_MS = 10_000;

const rtcConfig = {
	iceServers: [{ urls: 'stun:stun.l.google.com:19302' }]
};

let initialized = false;
let initPromise = null;
let socket = null;
let pollInterval = null;
let socketHeartbeatInterval = null;
let localCameraStream = null;
let activeMediaRecorder = null;
let activeRecordingChunks = [];
let activeRecordingStartedAt = null;
let activeRecordingStreamSessionId = null;
let lastMotionEventId = null;
let motionDetector = null;
let detectorMotionActive = false;
let autoMotionTransitionInFlight = false;

let cameraVideoElement = null;
let clientVideoElement = null;

const peerConnections = new Map();
const remoteStreams = new Map();
const hiddenClientStreamElements = new Map();
const pendingCandidatesMap = new Map();
const streamTimers = new Map();
const connectedPeers = new Set();
const requestedStreams = new Set();

const makeId = () => {
	if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
		return crypto.randomUUID();
	}
	return `${Date.now()}-${Math.random().toString(16).slice(2)}`;
};

const getDefaultMotionDetectionState = () => ({
	enabled: false,
	profile: MOTION_DETECTION_PROFILES.balanced.profile,
	state: 'idle',
	score: 0,
	debug: false,
	lastTriggeredAt: null
});

const getMotionDetectionProfile = (profile) =>
	MOTION_DETECTION_PROFILES[profile] ?? MOTION_DETECTION_PROFILES.balanced;

const buildMotionDetectionState = (overrides = {}) => {
	const defaults = getDefaultMotionDetectionState();
	const nextProfile = getMotionDetectionProfile(overrides.profile ?? defaults.profile);
	return {
		...defaults,
		...nextProfile,
		...overrides,
		profile: nextProfile.profile
	};
};

const sanitizeMotionDetectionSettings = (value) => {
	if (!value || typeof value !== 'object') {
		return buildMotionDetectionState();
	}

	return buildMotionDetectionState({
		enabled: Boolean(value.enabled),
		profile: typeof value.profile === 'string' ? value.profile : undefined,
		debug: Boolean(value.debug)
	});
};

const normalizeMotionDetectionState = (value) => {
	if (!value || typeof value !== 'object') {
		return buildMotionDetectionState();
	}

	return buildMotionDetectionState({
		enabled: Boolean(value.enabled),
		profile: typeof value.profile === 'string' ? value.profile : undefined,
		state: typeof value.state === 'string' ? value.state : undefined,
		score: typeof value.score === 'number' ? value.score : undefined,
		debug: Boolean(value.debug),
		lastTriggeredAt: typeof value.lastTriggeredAt === 'string' ? value.lastTriggeredAt : null
	});
};

const loadMotionDetectionSettings = () => {
	if (typeof localStorage === 'undefined') {
		return buildMotionDetectionState();
	}

	try {
		const saved = localStorage.getItem(MOTION_DETECTION_SETTINGS_STORAGE_KEY);
		if (!saved) {
			return buildMotionDetectionState();
		}
		return sanitizeMotionDetectionSettings(JSON.parse(saved));
	} catch (error) {
		console.error('Failed to load motion detection settings', error);
		return buildMotionDetectionState();
	}
};

const persistMotionDetectionSettings = (motionDetection) => {
	if (typeof localStorage === 'undefined') {
		return;
	}

	try {
		localStorage.setItem(
			MOTION_DETECTION_SETTINGS_STORAGE_KEY,
			JSON.stringify({
				enabled: Boolean(motionDetection?.enabled),
				profile: motionDetection?.profile ?? MOTION_DETECTION_PROFILES.balanced.profile,
				debug: Boolean(motionDetection?.debug)
			})
		);
	} catch (error) {
		console.error('Failed to save motion detection settings', error);
	}
};

const updateMotionDetectionState = (updates) => {
	const current = normalizeMotionDetectionState(getAppState().motionDetection);
	const next =
		typeof updates === 'function'
			? normalizeMotionDetectionState({
					...current,
					...updates(current)
				})
			: normalizeMotionDetectionState({
					...current,
					...updates
				});

	setAppState({ motionDetection: next });
	persistMotionDetectionSettings(next);
	return next;
};

const normalizePath = (path) => path.replace(/\/+$/, '') || '/';

const getCurrentPath = () => normalizePath(window.location.pathname);

const getHomePageKeyForRole = (role) => (role === 'camera' ? 'camera' : 'client');

const getPathForScreen = (screen, role) => {
	if (screen === 'home') {
		return PAGE_PATHS[getHomePageKeyForRole(role)];
	}
	return PAGE_PATHS[screen] || null;
};

const pageFromPath = (path) => {
	switch (normalizePath(path)) {
		case '/onboarding':
			return 'onboarding';
		case '/camera':
			return 'camera';
		case '/client':
			return 'client';
		case '/activity':
			return 'activity';
		case '/settings':
			return 'settings';
		default:
			return 'auth';
	}
};

const navigateToScreen = (screen, options = {}) => {
	const { replace = false, role = getAppState().device?.role } = options;
	const targetPath = getPathForScreen(screen, role);
	if (!targetPath) return false;

	if (getCurrentPath() !== normalizePath(targetPath)) {
		if (replace) {
			window.location.replace(targetPath);
		} else {
			window.location.assign(targetPath);
		}
		return true;
	}

	setAppState({ page: pageFromPath(targetPath) });
	return false;
};

const readSavedDeviceRecord = () => {
	if (typeof localStorage === 'undefined') {
		return null;
	}

	const saved = localStorage.getItem(DEVICE_STORAGE_KEY);
	if (!saved) {
		return null;
	}

	try {
		return JSON.parse(saved);
	} catch (error) {
		console.error('Failed to parse saved device', error);
		localStorage.removeItem(DEVICE_STORAGE_KEY);
		return null;
	}
};

const persistSavedDeviceRecord = ({ device, deviceToken, userId }) => {
	if (typeof localStorage === 'undefined') {
		return;
	}

	localStorage.setItem(
		DEVICE_STORAGE_KEY,
		JSON.stringify({
			device,
			deviceToken,
			userId
		})
	);
};

const clearSavedDeviceRecord = () => {
	if (typeof localStorage === 'undefined') {
		return;
	}

	localStorage.removeItem(DEVICE_STORAGE_KEY);
};

const applySavedDeviceState = (device, deviceToken) => {
	setAppState({
		device,
		deviceToken,
		onboardingForm: {
			...getAppState().onboardingForm,
			name: device?.name ?? '',
			role: device?.role ?? 'client',
			pushToken: ''
		}
	});
};

const clearDeviceState = () => {
	setAppState({
		device: null,
		deviceToken: null,
		socketConnected: false,
		isMotionActive: false,
		activeMotionSource: null,
		cameraStatus: 'idle',
		cameraPreviewReady: false,
		linkedCameras: [],
		recordings: [],
		activeCameraDeviceId: null,
		activeStreamSessionId: null,
		openLinkedCameraMenuId: null,
		cameraSessions: {},
		connectedStreamSessionIds: [],
		clientStreamMode: 'none',
		clientPlaceholderText: 'Select a camera to view',
		onboardingForm: {
			...getAppState().onboardingForm,
			name: '',
			role: 'client',
			pushToken: ''
		}
	});
};

const restoreSavedDeviceForSession = async (session, options = {}) => {
	const { showMissingToast = false, showInvalidToast = false } = options;
	const saved = readSavedDeviceRecord();

	if (!saved) {
		if (showMissingToast) {
			pushToast('No saved device found', 'info');
		}
		return false;
	}

	const sessionUserId = session?.user?.id;
	const savedUserId = typeof saved.userId === 'string' ? saved.userId : null;
	const savedDeviceId = saved?.device?.id;
	const savedDeviceToken = typeof saved?.deviceToken === 'string' ? saved.deviceToken : '';

	if (!sessionUserId || !savedDeviceId || !savedDeviceToken) {
		clearSavedDeviceRecord();
		clearDeviceState();
		if (showInvalidToast) {
			pushToast('Saved device is incomplete. Please register again.', 'error');
		}
		return false;
	}

	if (savedUserId && savedUserId !== sessionUserId) {
		clearSavedDeviceRecord();
		clearDeviceState();
		if (showInvalidToast) {
			pushToast('Saved device belongs to a different account.', 'info');
		}
		return false;
	}

	try {
		const result = await api.devices.list();
		const matchingDevice = result.devices?.find((device) => device.id === savedDeviceId);

		if (!matchingDevice) {
			clearSavedDeviceRecord();
			clearDeviceState();
			if (showInvalidToast) {
				pushToast('Saved device was not found for this account.', 'info');
			}
			return false;
		}

		applySavedDeviceState(matchingDevice, savedDeviceToken);
		persistSavedDeviceRecord({
			device: matchingDevice,
			deviceToken: savedDeviceToken,
			userId: sessionUserId
		});
		return true;
	} catch (error) {
		console.error('Failed to restore saved device', error);
		if (showInvalidToast) {
			pushToast('Unable to restore saved device right now.', 'error');
		}
		return false;
	}
};

const setConnectedStreamSessionIds = () => {
	setAppState({ connectedStreamSessionIds: Array.from(connectedPeers) });
};

const pushToast = (message, type = 'info') => {
	const id = makeId();
	patchAppState((state) => ({
		toasts: [...state.toasts, { id, message, type }].slice(-6)
	}));

	setTimeout(() => {
		patchAppState((state) => ({
			toasts: state.toasts.filter((toast) => toast.id !== id)
		}));
	}, 3200);
};

const removeToast = (id) => {
	patchAppState((state) => ({
		toasts: state.toasts.filter((toast) => toast.id !== id)
	}));
};

const addActivity = (type, message) => {
	const item = {
		id: makeId(),
		type,
		message,
		createdAt: new Date().toISOString()
	};

	patchAppState((state) => ({
		activityLog: [item, ...state.activityLog].slice(0, 200)
	}));
};

const setClientStreamMode = (mode) => {
	let clientPlaceholderText = 'Select a camera to view';
	if (mode === 'connecting') clientPlaceholderText = 'Connecting stream...';
	if (mode === 'unavailable') clientPlaceholderText = 'Stream unavailable';
	if (mode === 'none') clientPlaceholderText = 'Select a camera to view';

	patchAppState(() => ({
		clientStreamMode: mode,
		clientPlaceholderText
	}));
};

const getCameraDeviceIdFromStream = (stream) => {
	if (!stream) return '';
	const videoTrack = stream.getVideoTracks?.()[0];
	if (!videoTrack) return '';
	const settings = videoTrack.getSettings?.() || {};
	return typeof settings.deviceId === 'string' ? settings.deviceId : '';
};

const buildCameraConstraints = (cameraDeviceId = '') => {
	if (!cameraDeviceId) return { ...DEFAULT_CAMERA_CONSTRAINTS };
	return {
		...DEFAULT_CAMERA_CONSTRAINTS,
		deviceId: { exact: cameraDeviceId }
	};
};

const refreshCameraInputDevices = async () => {
	if (!navigator.mediaDevices?.enumerateDevices) {
		setAppState({ cameraInputDevices: [], selectedCameraInputId: '' });
		return [];
	}

	try {
		const devices = await navigator.mediaDevices.enumerateDevices();
		const cameraInputDevices = devices
			.filter((device) => device.kind === 'videoinput' && device.deviceId)
			.map((device, index) => ({
				id: device.deviceId,
				label: device.label || `Camera ${index + 1}`
			}));

		const selectedCameraInputId = getAppState().selectedCameraInputId;
		const streamCameraInputId = getCameraDeviceIdFromStream(localCameraStream);
		const candidateCameraInputId = selectedCameraInputId || streamCameraInputId || '';
		const nextSelectedCameraInputId = cameraInputDevices.some((device) => device.id === candidateCameraInputId)
			? candidateCameraInputId
			: (cameraInputDevices[0]?.id ?? '');

		setAppState({
			cameraInputDevices,
			selectedCameraInputId: nextSelectedCameraInputId
		});
		return cameraInputDevices;
	} catch (error) {
		console.error('Failed to enumerate cameras', error);
		addActivity('Camera', 'Failed to enumerate camera inputs');
		return [];
	}
};

const onMediaDeviceChange = () => {
	void refreshCameraInputDevices();
};

const attachCameraStreamToElement = () => {
	if (!cameraVideoElement) return;
	cameraVideoElement.srcObject = localCameraStream;
	if (localCameraStream) {
		void cameraVideoElement.play().catch(() => {});
	}
	applyMotionDetectionReadiness();
};

const attachClientStreamToElement = () => {
	if (!clientVideoElement) return;
	const { activeStreamSessionId } = getAppState();
	if (!activeStreamSessionId) {
		clientVideoElement.srcObject = null;
		return;
	}
	const stream = remoteStreams.get(activeStreamSessionId);
	if (!stream) return;
	if (clientVideoElement.srcObject !== stream) {
		clientVideoElement.srcObject = stream;
	}
	clientVideoElement.muted = true;
	void clientVideoElement.play().catch((error) => {
		addActivity('Stream', `Autoplay blocked for ${activeStreamSessionId}: ${error?.name || 'play_failed'}`);
	});
};

const primeClientStreamPlayback = (streamSessionId, stream) => {
	if (!streamSessionId || !stream) return;

	let hiddenVideoElement = hiddenClientStreamElements.get(streamSessionId);
	if (!hiddenVideoElement && typeof document !== 'undefined') {
		hiddenVideoElement = document.createElement('video');
		hiddenVideoElement.muted = true;
		hiddenVideoElement.autoplay = true;
		hiddenVideoElement.playsInline = true;
		hiddenVideoElement.style.position = 'fixed';
		hiddenVideoElement.style.width = '1px';
		hiddenVideoElement.style.height = '1px';
		hiddenVideoElement.style.opacity = '0';
		hiddenVideoElement.style.pointerEvents = 'none';
		hiddenVideoElement.style.left = '-9999px';
		hiddenVideoElement.style.top = '-9999px';
		document.body.appendChild(hiddenVideoElement);
		hiddenClientStreamElements.set(streamSessionId, hiddenVideoElement);
	}

	if (!hiddenVideoElement) return;
	if (hiddenVideoElement.srcObject !== stream) {
		hiddenVideoElement.srcObject = stream;
	}
	void hiddenVideoElement.play().catch(() => {});
};

const startCameraPreview = async (cameraInputId = getAppState().selectedCameraInputId) => {
	if (!navigator.mediaDevices?.getUserMedia) {
		pushToast('Camera API is not available in this browser', 'error');
		return false;
	}

	const requestedCameraInputId = typeof cameraInputId === 'string' ? cameraInputId.trim() : '';
	const activeCameraInputId = getCameraDeviceIdFromStream(localCameraStream);

	if (localCameraStream) {
		if (!requestedCameraInputId || requestedCameraInputId === activeCameraInputId) {
			attachCameraStreamToElement();
			setAppState({ cameraPreviewReady: true });
			void refreshCameraInputDevices();
			return true;
		}

		localCameraStream.getTracks().forEach((track) => track.stop());
		localCameraStream = null;
	}

	const constraintCandidates = [];
	if (requestedCameraInputId) {
		constraintCandidates.push(
			{
				video: buildCameraConstraints(requestedCameraInputId),
				audio: false
			},
			{
				video: {
					deviceId: { exact: requestedCameraInputId }
				},
				audio: false
			}
		);
	}

	constraintCandidates.push(
		{
			video: buildCameraConstraints(),
			audio: false
		},
		{
			video: true,
			audio: false
		}
	);

	let lastError = null;
	for (const constraints of constraintCandidates) {
		try {
			localCameraStream = await navigator.mediaDevices.getUserMedia(constraints);
			break;
		} catch (error) {
			lastError = error;
		}
	}

	if (!localCameraStream) {
		pushToast('Camera permission denied or unavailable', 'error');
		addActivity('Camera', 'Camera access failed');
		setAppState({ cameraPreviewReady: false });
		return false;
	}

	const nextSelectedCameraInputId = getCameraDeviceIdFromStream(localCameraStream) || requestedCameraInputId || '';
	attachCameraStreamToElement();
	setAppState({
		cameraPreviewReady: true,
		selectedCameraInputId: nextSelectedCameraInputId
	});
	await refreshCameraInputDevices();

	if (requestedCameraInputId && nextSelectedCameraInputId && nextSelectedCameraInputId !== requestedCameraInputId) {
		pushToast('Selected camera unavailable, using another camera', 'info');
	}
	if (lastError && !requestedCameraInputId) {
		addActivity('Camera', `Applied fallback camera constraints (${lastError.name || 'unknown_error'})`);
	}
	addActivity('Camera', 'Camera access granted');
	return true;
};

const stopCameraPreview = () => {
	if (localCameraStream) {
		localCameraStream.getTracks().forEach((track) => track.stop());
		localCameraStream = null;
	}
	if (cameraVideoElement) {
		cameraVideoElement.srcObject = null;
	}
	setAppState({ cameraPreviewReady: false });
	applyMotionDetectionReadiness();
};

const updateMotionDetectionRuntime = (updates) => {
	patchAppState((state) => ({
		motionDetection: {
			...state.motionDetection,
			...updates
		}
	}));
};

const isAutoMotionEventActive = () => {
	const state = getAppState();
	return Boolean(state.isMotionActive && state.activeMotionSource === 'auto' && lastMotionEventId);
};

const getMotionDetectionPauseReason = () => {
	if (typeof document !== 'undefined' && document.visibilityState !== 'visible') {
		return 'page hidden';
	}

	const state = getAppState();
	if (state.device?.role !== 'camera') {
		return 'device is not a camera';
	}
	if (!state.motionDetection?.enabled) {
		return 'detector disarmed';
	}
	if (!state.socketConnected) {
		return 'realtime connection offline';
	}
	if (!state.cameraPreviewReady) {
		return 'camera preview unavailable';
	}
	if (!localCameraStream) {
		return 'camera stream unavailable';
	}
	if (!cameraVideoElement) {
		return 'preview element unavailable';
	}
	return 'idle';
};

const ensureMotionDetector = () => {
	if (motionDetector) {
		return motionDetector;
	}

	motionDetector = createMotionDetector({
		getSourceElement: () => cameraVideoElement,
		getConfig: () => getAppState().motionDetection,
		onUpdate: ({ state, score, activeMotion, activeSince }) => {
			const current = getAppState().motionDetection;
			const nextState = state === 'cooldown' && !activeMotion ? 'monitoring' : state;
			const motionBecameActive = activeMotion && !detectorMotionActive;
			const motionBecameInactive = !activeMotion && detectorMotionActive;
			detectorMotionActive = activeMotion;
			updateMotionDetectionRuntime({
				state: nextState,
				score,
				lastTriggeredAt: motionBecameActive
					? activeSince
						? new Date(activeSince).toISOString()
						: new Date().toISOString()
					: current.lastTriggeredAt
			});

			if (motionBecameActive || motionBecameInactive) {
				void syncAutoMotionLifecycle({ activeMotion });
			}
		}
	});

	return motionDetector;
};

const shouldRunMotionDetector = () => {
	if (typeof document !== 'undefined' && document.visibilityState !== 'visible') {
		return false;
	}

	const state = getAppState();
	return Boolean(
		state.device?.role === 'camera' &&
		state.motionDetection?.enabled &&
		state.socketConnected &&
		state.cameraPreviewReady &&
		localCameraStream &&
		cameraVideoElement
	);
};

const applyMotionDetectionReadiness = () => {
	const detector = ensureMotionDetector();
	if (shouldRunMotionDetector()) {
		if (!detector.isRunning()) {
			detector.start();
			addActivity('Motion Detection', 'Detector monitoring started');
		}
		return;
	}

	const pauseReason = getMotionDetectionPauseReason();
	detectorMotionActive = false;
	if (isAutoMotionEventActive()) {
		void syncAutoMotionLifecycle({ activeMotion: false });
	}

	if (detector.isRunning()) {
		detector.stop('idle');
		addActivity('Motion Detection', `Detector monitoring paused (${pauseReason})`);
		return;
	}

	updateMotionDetectionRuntime({ state: 'idle', score: 0 });
};

const onVisibilityChange = () => {
	applyMotionDetectionReadiness();
};

const clearClientStream = () => {
	const { activeStreamSessionId } = getAppState();
	if (activeStreamSessionId && streamTimers.has(activeStreamSessionId)) {
		clearTimeout(streamTimers.get(activeStreamSessionId));
		streamTimers.delete(activeStreamSessionId);
	}

	if (activeStreamSessionId && remoteStreams.has(activeStreamSessionId)) {
		remoteStreams.get(activeStreamSessionId)?.getTracks().forEach((track) => track.stop());
		remoteStreams.delete(activeStreamSessionId);
	}

	if (clientVideoElement) {
		clientVideoElement.srcObject = null;
	}

	setClientStreamMode('none');
};

const endClientStreamSession = async (streamSessionId, { teardown = true } = {}) => {
	if (!streamSessionId) return;

	try {
		await api.streams.end(streamSessionId);
	} catch (error) {
		const message = error?.message || '';
		if (!/cannot be ended|not found/i.test(message)) {
			console.warn('Failed ending client stream session', error);
		}
	}

	if (teardown) {
		teardownPeerConnection(streamSessionId);
	}
};

const hasReusableClientStreamSession = (streamSessionId) =>
	Boolean(streamSessionId && (remoteStreams.has(streamSessionId) || streamTimers.has(streamSessionId)));

const removeCameraSessionMapping = (streamSessionId) => {
	if (!streamSessionId) return;

	patchAppState((state) => ({
		cameraSessions: Object.fromEntries(
			Object.entries(state.cameraSessions || {}).filter(([, sessionId]) => sessionId !== streamSessionId)
		)
	}));
};

const getLinkedCamera = (cameraDeviceId) =>
	getAppState().linkedCameras.find((camera) => camera.cameraDeviceId === cameraDeviceId);

const getCameraLabel = (cameraDeviceId, cameraName) => {
	const explicitName = typeof cameraName === 'string' ? cameraName.trim() : '';
	if (explicitName) return explicitName;

	const linkedName = getLinkedCamera(cameraDeviceId)?.cameraName;
	if (typeof linkedName === 'string' && linkedName.trim()) {
		return linkedName.trim();
	}

	return `Camera ${cameraDeviceId?.substring(0, 6) ?? 'Unknown'}`;
};

const mapNotificationDeliveryToMotionNotification = (delivery) => {
	const payload = delivery?.payload ?? {};
	const cameraDeviceId = typeof payload.cameraDeviceId === 'string' ? payload.cameraDeviceId : '';
	const deliveryType = typeof delivery?.type === 'string' ? delivery.type : '';

	if (deliveryType !== 'motion_detected') {
		return null;
	}

	return {
		id: delivery.id,
		eventId: typeof payload.eventId === 'string' ? payload.eventId : null,
		cameraDeviceId,
		message: `${getCameraLabel(cameraDeviceId)} has detected movement`,
		createdAt: delivery.sentAt || delivery.createdAt || new Date().toISOString(),
		isRead: delivery.status === 'read'
	};
};

const syncMotionNotificationsFromDeliveries = (deliveries) => {
	const motionNotifications = (deliveries || [])
		.map(mapNotificationDeliveryToMotionNotification)
		.filter(Boolean)
		.sort((left, right) => new Date(right.createdAt).getTime() - new Date(left.createdAt).getTime());

	setAppState({ motionNotifications });
};

const refreshMotionNotifications = async () => {
	const { device } = getAppState();
	if (!device || device.role !== 'client') {
		setAppState({ motionNotifications: [] });
		return [];
	}

	const result = await api.ops.listNotifications().catch(() => ({ notifications: [] }));
	syncMotionNotificationsFromDeliveries(result.notifications);
	return result.notifications || [];
};

const pushMotionNotification = (cameraDeviceId) => {
	if (!cameraDeviceId) return;

	const notification = {
		id: makeId(),
		eventId: null,
		cameraDeviceId,
		message: `${getCameraLabel(cameraDeviceId)} has detected movement`,
		createdAt: new Date().toISOString(),
		isRead: false
	};

	patchAppState((state) => ({
		motionNotifications: [notification, ...state.motionNotifications].slice(0, 50)
	}));

	void refreshMotionNotifications();
};

const markMotionNotificationRead = async (notificationId) => {
	patchAppState((state) => ({
		motionNotifications: state.motionNotifications.map((notification) =>
			notification.id === notificationId ? { ...notification, isRead: true } : notification
		)
	}));

	try {
		await api.pushNotifications.markRead(notificationId);
	} catch (error) {
		console.error('Failed to persist notification read state', error);
	}
};

const markAllNotificationsRead = async () => {
	const unreadIds = getAppState().motionNotifications.filter((notification) => !notification.isRead).map((notification) => notification.id);

	if (unreadIds.length === 0) {
		return;
	}

	patchAppState((state) => ({
		motionNotifications: state.motionNotifications.map((notification) =>
			notification.isRead ? notification : { ...notification, isRead: true }
		)
	}));

	await Promise.allSettled(unreadIds.map((notificationId) => api.pushNotifications.markRead(notificationId)));
};

const openRecordingModal = (downloadUrl, title) => {
	setAppState({
		recordingModal: {
			open: true,
			title: title || 'Recording Playback',
			url: downloadUrl
		}
	});
};

const closeRecordingModal = () => {
	setAppState({
		recordingModal: {
			open: false,
			title: 'Recording Playback',
			url: ''
		}
	});
};

const getPreferredRecordingMimeType = () => {
	if (typeof MediaRecorder === 'undefined') return '';
	const preferredTypes = ['video/webm;codecs=vp9', 'video/webm;codecs=vp8', 'video/webm'];
	return preferredTypes.find((type) => MediaRecorder.isTypeSupported(type)) ?? '';
};

const startLocalRecording = async () => {
	if (!localCameraStream || typeof MediaRecorder === 'undefined') {
		addActivity('Recording', 'MediaRecorder unavailable');
		return false;
	}

	if (activeMediaRecorder?.state === 'recording') {
		return true;
	}

	activeRecordingChunks = [];
	activeRecordingStartedAt = Date.now();

	try {
		const mimeType = getPreferredRecordingMimeType();
		const recorderOptions = {
			videoBitsPerSecond: RECORDING_VIDEO_BITS_PER_SECOND
		};
		if (mimeType) {
			recorderOptions.mimeType = mimeType;
		}
		activeMediaRecorder = new MediaRecorder(localCameraStream, recorderOptions);
	} catch (error) {
		console.error('Failed to create MediaRecorder', error);
		addActivity('Recording', 'Failed to start recorder');
		activeMediaRecorder = null;
		return false;
	}

	activeMediaRecorder.ondataavailable = (event) => {
		if (event.data && event.data.size > 0) {
			activeRecordingChunks.push(event.data);
		}
	};

	activeMediaRecorder.start(1000);
	setAppState({ cameraStatus: 'recording' });
	addActivity('Recording', 'Local recording started');
	return true;
};

const stopLocalRecording = async () => {
	if (!activeMediaRecorder || activeMediaRecorder.state === 'inactive') {
		setAppState({ cameraStatus: 'idle' });
		return null;
	}

	return await new Promise((resolve) => {
		const recorder = activeMediaRecorder;
		const startedAt = activeRecordingStartedAt ?? Date.now();

		recorder.onstop = () => {
			const mimeType = recorder.mimeType || 'video/webm';
			const blob = activeRecordingChunks.length > 0 ? new Blob(activeRecordingChunks, { type: mimeType }) : null;
			const durationSeconds = Math.max(1, Math.round((Date.now() - startedAt) / 1000));

			activeMediaRecorder = null;
			activeRecordingChunks = [];
			activeRecordingStartedAt = null;
			setAppState({ cameraStatus: 'idle' });

			resolve(blob ? { blob, durationSeconds } : null);
		};

		recorder.onerror = () => {
			activeMediaRecorder = null;
			activeRecordingChunks = [];
			activeRecordingStartedAt = null;
			setAppState({ cameraStatus: 'idle' });
			resolve(null);
		};

		recorder.stop();
	});
};

const toEvenDimension = (value) => {
	const rounded = Math.max(2, Math.floor(value));
	return rounded % 2 === 0 ? rounded : rounded - 1;
};

const compressRecordingBlob = async (sourceBlob) => {
	if (!sourceBlob || sourceBlob.size === 0) return sourceBlob;
	if (typeof document === 'undefined' || typeof MediaRecorder === 'undefined') return sourceBlob;

	const mimeType = getPreferredRecordingMimeType();
	if (!mimeType) return sourceBlob;

	const sourceUrl = URL.createObjectURL(sourceBlob);
	const videoEl = document.createElement('video');
	videoEl.muted = true;
	videoEl.playsInline = true;
	videoEl.preload = 'auto';

	let rafId = null;
	let captureStream = null;

	try {
		await new Promise((resolve, reject) => {
			videoEl.onloadedmetadata = resolve;
			videoEl.onerror = () => reject(new Error('Failed loading recorded clip'));
			videoEl.src = sourceUrl;
		});

		const sourceWidth = videoEl.videoWidth || COMPRESSED_UPLOAD_MAX_WIDTH;
		const sourceHeight = videoEl.videoHeight || COMPRESSED_UPLOAD_MAX_HEIGHT;
		const scale = Math.min(1, COMPRESSED_UPLOAD_MAX_WIDTH / sourceWidth, COMPRESSED_UPLOAD_MAX_HEIGHT / sourceHeight);
		const width = toEvenDimension(sourceWidth * scale);
		const height = toEvenDimension(sourceHeight * scale);

		const canvas = document.createElement('canvas');
		canvas.width = width;
		canvas.height = height;
		const context = canvas.getContext('2d');
		if (!context || typeof canvas.captureStream !== 'function') {
			return sourceBlob;
		}

		captureStream = canvas.captureStream(COMPRESSED_UPLOAD_FRAME_RATE);
		const compressedChunks = [];
		const recorder = new MediaRecorder(captureStream, {
			mimeType,
			videoBitsPerSecond: COMPRESSED_UPLOAD_BITS_PER_SECOND
		});

		const recorderStopped = new Promise((resolve, reject) => {
			recorder.ondataavailable = (event) => {
				if (event.data?.size > 0) {
					compressedChunks.push(event.data);
				}
			};
			recorder.onerror = (event) => {
				const message = event?.error?.message || 'Compression recorder failed';
				reject(new Error(message));
			};
			recorder.onstop = () => {
				resolve(new Blob(compressedChunks, { type: recorder.mimeType || mimeType }));
			};
		});

		const drawFrame = () => {
			if (videoEl.paused || videoEl.ended) return;
			context.drawImage(videoEl, 0, 0, width, height);
			rafId = requestAnimationFrame(drawFrame);
		};

		recorder.start(300);
		await videoEl.play();
		drawFrame();

		await new Promise((resolve, reject) => {
			videoEl.onended = resolve;
			videoEl.onerror = () => reject(new Error('Failed during compression playback'));
		});

		if (rafId !== null) {
			cancelAnimationFrame(rafId);
			rafId = null;
		}
		recorder.stop();
		const compressedBlob = await recorderStopped;
		if (!compressedBlob || compressedBlob.size === 0 || compressedBlob.size >= sourceBlob.size) {
			return sourceBlob;
		}

		const reductionPct = Math.round(((sourceBlob.size - compressedBlob.size) / sourceBlob.size) * 100);
		addActivity('Recording', `Compressed clip by ${reductionPct}% before upload`);
		return compressedBlob;
	} catch (error) {
		console.warn('Recording compression failed, uploading original clip', error);
		return sourceBlob;
	} finally {
		if (rafId !== null) {
			cancelAnimationFrame(rafId);
		}
		if (captureStream) {
			captureStream.getTracks().forEach((track) => track.stop());
		}
		videoEl.pause();
		videoEl.removeAttribute('src');
		videoEl.load();
		URL.revokeObjectURL(sourceUrl);
	}
};

const teardownPeerConnection = (streamSessionId) => {
	if (!streamSessionId) {
		for (const connection of peerConnections.values()) {
			connection.close();
		}
		peerConnections.clear();
		remoteStreams.clear();
		for (const hiddenVideoElement of hiddenClientStreamElements.values()) {
			hiddenVideoElement.pause();
			hiddenVideoElement.srcObject = null;
			hiddenVideoElement.remove();
		}
		hiddenClientStreamElements.clear();
		pendingCandidatesMap.clear();
		connectedPeers.clear();
		setConnectedStreamSessionIds();
		setAppState({ cameraSessions: {} });
		clearClientStream();
		return;
	}

	if (peerConnections.has(streamSessionId)) {
		peerConnections.get(streamSessionId)?.close();
		peerConnections.delete(streamSessionId);
	}
	remoteStreams.delete(streamSessionId);
	if (hiddenClientStreamElements.has(streamSessionId)) {
		const hiddenVideoElement = hiddenClientStreamElements.get(streamSessionId);
		hiddenVideoElement?.pause();
		if (hiddenVideoElement) {
			hiddenVideoElement.srcObject = null;
			hiddenVideoElement.remove();
		}
		hiddenClientStreamElements.delete(streamSessionId);
	}
	pendingCandidatesMap.delete(streamSessionId);
	connectedPeers.delete(streamSessionId);
	setConnectedStreamSessionIds();
	removeCameraSessionMapping(streamSessionId);

	if (getAppState().activeStreamSessionId === streamSessionId) {
		clearClientStream();
	}
};

const queueRemoteCandidate = ({ streamSessionId, fromDeviceId, data }) => {
	if (!streamSessionId || !fromDeviceId || !data) return;
	if (!pendingCandidatesMap.has(streamSessionId)) {
		pendingCandidatesMap.set(streamSessionId, []);
	}
	const queue = pendingCandidatesMap.get(streamSessionId);
	queue.push({ streamSessionId, fromDeviceId, data, createdAt: Date.now() });
	const cutoff = Date.now() - 120000;
	pendingCandidatesMap.set(
		streamSessionId,
		queue.filter((item) => item.createdAt >= cutoff).slice(-200)
	);
};

const takeQueuedCandidates = (streamSessionId, fromDeviceId) => {
	if (!pendingCandidatesMap.has(streamSessionId)) return [];
	const queue = pendingCandidatesMap.get(streamSessionId);
	const queued = queue.filter((item) => item.fromDeviceId === fromDeviceId);
	pendingCandidatesMap.set(
		streamSessionId,
		queue.filter((item) => item.fromDeviceId !== fromDeviceId)
	);
	return queued;
};

const applyQueuedCandidates = async (connection, streamSessionId, fromDeviceId) => {
	if (!connection?.remoteDescription) return;
	const queued = takeQueuedCandidates(streamSessionId, fromDeviceId);
	for (const candidate of queued) {
		try {
			await connection.addIceCandidate(new RTCIceCandidate(candidate.data));
		} catch (error) {
			console.warn('Dropping queued ICE candidate', error);
		}
	}
};

const ensurePeerConnection = async ({ streamSessionId, targetDeviceId, asCamera }) => {
	if (peerConnections.has(streamSessionId)) {
		return peerConnections.get(streamSessionId);
	}

	const connection = new RTCPeerConnection(rtcConfig);
	peerConnections.set(streamSessionId, connection);

	connection.onicecandidate = (event) => {
		if (!socket || !event.candidate) return;
		socket.emit('webrtc:signal', {
			toDeviceId: targetDeviceId,
			streamSessionId,
			signalType: 'candidate',
			data: event.candidate.toJSON()
		});
	};

	connection.onconnectionstatechange = () => {
		if (connection.connectionState === 'connected') {
			addActivity('WebRTC', `Peer connected for ${streamSessionId}`);
			connectedPeers.add(streamSessionId);
			setConnectedStreamSessionIds();
		} else if (
			connection.connectionState === 'failed' ||
			connection.connectionState === 'disconnected' ||
			connection.connectionState === 'closed'
		) {
			addActivity('WebRTC', `Peer ${connection.connectionState} for ${streamSessionId}`);
			connectedPeers.delete(streamSessionId);
			setConnectedStreamSessionIds();
			if (getAppState().device?.role === 'client' && getAppState().activeStreamSessionId === streamSessionId) {
				if (connection.connectionState === 'failed' || connection.connectionState === 'closed') {
					setClientStreamMode('unavailable');
				}
			}
		}
	};

	connection.ontrack = (event) => {
		if (streamTimers.has(streamSessionId)) {
			clearTimeout(streamTimers.get(streamSessionId));
			streamTimers.delete(streamSessionId);
		}

		const [stream] = event.streams;
		if (!stream) return;

		connectedPeers.add(streamSessionId);
		setConnectedStreamSessionIds();
		remoteStreams.set(streamSessionId, stream);

		if (getAppState().activeStreamSessionId === streamSessionId) {
			attachClientStreamToElement();
			setClientStreamMode('video');
			return;
		}

		primeClientStreamPlayback(streamSessionId, stream);
	};

	if (asCamera) {
		const ready = await startCameraPreview();
		if (!ready || !localCameraStream || localCameraStream.getVideoTracks().length === 0) {
			throw new Error('Camera stream unavailable for WebRTC publish');
		}
		localCameraStream.getTracks().forEach((track) => connection.addTrack(track, localCameraStream));
	}

	return connection;
};

const startOfferToClient = async (streamSessionId, requesterDeviceId) => {
	if (!socket) return;

	const connection = await ensurePeerConnection({
		streamSessionId,
		targetDeviceId: requesterDeviceId,
		asCamera: true
	});

	const offer = await connection.createOffer();
	await connection.setLocalDescription(offer);
	socket.emit('webrtc:signal', {
		toDeviceId: requesterDeviceId,
		streamSessionId,
		signalType: 'offer',
		data: offer
	});
};

const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const finalizeRecordingForStream = async (streamSessionId, captureResult) => {
	const currentDevice = getAppState().device;
	if (!currentDevice?.id) {
		addActivity('Recording', 'No device identity for finalize');
		return false;
	}

	for (let attempt = 0; attempt < 8; attempt += 1) {
		const recs = await api.ops.listRecordings().catch(() => ({ recordings: [] }));
		const recording = (recs.recordings || []).find(
			(rec) => rec.streamSessionId === streamSessionId && rec.status === 'awaiting_upload'
		);

		if (recording?.id) {
			try {
				if (!captureResult?.blob || captureResult.blob.size === 0) {
					throw new Error('No captured video blob to upload');
				}
				const compressedBlob = await compressRecordingBlob(captureResult.blob);

				const uploadMeta = await api.request('/videos/upload-url', {
					method: 'POST',
					body: JSON.stringify({
						fileName: `stream-${streamSessionId}.webm`,
						deviceId: currentDevice.id,
						prefix: 'recordings',
						recordingId: recording.id
					})
				});

				const uploadResponse = await fetch(uploadMeta.uploadUrl, {
					method: 'PUT',
					headers: { 'Content-Type': compressedBlob.type || 'video/webm' },
					body: compressedBlob
				});

				if (!uploadResponse.ok) {
					throw new Error(`Upload failed with status ${uploadResponse.status}`);
				}

				await api.events.finalizeRecording(recording.id, {
					objectKey: uploadMeta.objectKey,
					bucket: uploadMeta.bucket,
					durationSeconds: captureResult.durationSeconds,
					sizeBytes: compressedBlob.size
				});

				addActivity('Recording', 'Recording uploaded and finalized');
				return true;
			} catch (error) {
				console.error('Recording upload failed, falling back to simulated key', error);
				const fallbackObjectKey = `sim/${streamSessionId}/${Date.now()}.webm`;
				await api.events.finalizeRecording(recording.id, {
					objectKey: fallbackObjectKey,
					durationSeconds: captureResult?.durationSeconds ?? 15,
					sizeBytes: captureResult?.blob?.size ?? 5000000
				});
				addActivity('Recording', 'Upload failed; finalized with simulator fallback');
				return true;
			}
		}

		await sleep(350);
	}

	addActivity('Recording', 'No recording row found to finalize');
	return false;
};

const uploadStandaloneMotionRecording = async (captureResult) => {
	const currentDevice = getAppState().device;
	if (!currentDevice?.id) {
		addActivity('Recording', 'Cannot upload motion clip without device identity');
		return false;
	}

	if (!captureResult?.blob || captureResult.blob.size === 0) {
		addActivity('Recording', 'No motion clip captured for upload');
		return false;
	}

	try {
		const compressedBlob = await compressRecordingBlob(captureResult.blob);
		const uploadMeta = await api.request('/videos/upload-url', {
			method: 'POST',
			body: JSON.stringify({
				fileName: `motion-${Date.now()}.webm`,
				deviceId: currentDevice.id,
				prefix: 'recordings',
				eventId: lastMotionEventId
			})
		});

		const uploadResponse = await fetch(uploadMeta.uploadUrl, {
			method: 'PUT',
			headers: { 'Content-Type': compressedBlob.type || 'video/webm' },
			body: compressedBlob
		});

		if (!uploadResponse.ok) {
			throw new Error(`Upload failed with status ${uploadResponse.status}`);
		}

		await api.events.finalizeRecording(uploadMeta.video.id, {
			objectKey: uploadMeta.objectKey,
			bucket: uploadMeta.bucket,
			durationSeconds: captureResult.durationSeconds,
			sizeBytes: compressedBlob.size
		});

		addActivity('Recording', `Motion clip uploaded (${uploadMeta.objectKey})`);
		return true;
	} catch (error) {
		console.error('Standalone motion upload failed', error);
		addActivity('Recording', 'Standalone motion upload failed');
		return false;
	}
};

const getMotionStartPayload = (source = 'manual') =>
	source === 'auto'
		? { title: 'Automatic Motion', triggeredBy: 'auto_motion' }
		: { title: 'Simulated Motion', triggeredBy: 'motion' };

const startMotionEvent = async ({ source = 'manual' } = {}) => {
	if (getAppState().isMotionActive || lastMotionEventId) {
		return false;
	}

	const response = await api.events.startMotion(getMotionStartPayload(source));
	await startCameraPreview();
	await startLocalRecording();
	lastMotionEventId = response.event.id;

	const startedAt = new Date().toISOString();
	setAppState({
		isMotionActive: true,
		activeMotionSource: source
	});

	if (source === 'auto') {
		updateMotionDetectionRuntime({ lastTriggeredAt: startedAt });
	}

	pushToast(source === 'auto' ? 'Automatic motion event started' : 'Motion Event Started', 'success');
	addActivity(
		'Motion',
		source === 'auto' ? `Automatic motion event started (${response.event.id})` : `Started event ${response.event.id}`
	);
	return true;
};

const endMotionEvent = async ({ source = 'manual' } = {}) => {
	if (!lastMotionEventId) {
		return false;
	}

	const eventId = lastMotionEventId;
	const streamSessionId = activeRecordingStreamSessionId;

	if (streamSessionId) {
		await api.streams.end(streamSessionId);
		addActivity('Stream', `Ended stream ${streamSessionId}`);
	} else if (activeMediaRecorder?.state === 'recording') {
		const captureResult = await stopLocalRecording();
		await uploadStandaloneMotionRecording(captureResult);
	}

	await api.events.endMotion(eventId);
	lastMotionEventId = null;
	setAppState({
		isMotionActive: false,
		activeMotionSource: null
	});

	pushToast(source === 'auto' ? 'Automatic motion event ended' : 'Motion Ended', 'success');
	addActivity(
		'Motion',
		source === 'auto' ? `Automatic motion event ended (${eventId})` : `Ended event ${eventId}`
	);
	return true;
};

const syncAutoMotionLifecycle = async ({ activeMotion }) => {
	if (autoMotionTransitionInFlight) {
		return;
	}

	if (activeMotion) {
		if (getAppState().isMotionActive || lastMotionEventId) {
			return;
		}

		autoMotionTransitionInFlight = true;
		try {
			await startMotionEvent({ source: 'auto' });
		} catch (error) {
			console.error('Failed to auto-start motion event', error);
			pushToast(error.message || 'Failed to start automatic motion event', 'error');
		} finally {
			autoMotionTransitionInFlight = false;
		}
		return;
	}

	if (!isAutoMotionEventActive()) {
		return;
	}

	autoMotionTransitionInFlight = true;
	try {
		await endMotionEvent({ source: 'auto' });
	} catch (error) {
		console.error('Failed to auto-end motion event', error);
		pushToast(error.message || 'Failed to end automatic motion event', 'error');
	} finally {
		autoMotionTransitionInFlight = false;
	}
};

const handleCameraStreamRequest = async ({ streamId, requesterDeviceId }) => {
	if (!streamId || !requesterDeviceId) {
		throw new Error('Missing stream request context');
	}

	const ready = await startCameraPreview();
	if (!ready) {
		throw new Error('Camera permission is required before streaming');
	}

	activeRecordingStreamSessionId = streamId;
	await api.streams.accept(streamId);
	await startLocalRecording();
	await startOfferToClient(streamId, requesterDeviceId);
	addActivity('Stream', 'Accepted stream request and started WebRTC offer');
};

const stopSocketHeartbeat = () => {
	if (socketHeartbeatInterval) {
		clearInterval(socketHeartbeatInterval);
		socketHeartbeatInterval = null;
	}
};

const emitSocketHeartbeat = () => {
	if (!socket?.connected) {
		return;
	}

	socket.emit('heartbeat');
};

const startSocketHeartbeat = () => {
	stopSocketHeartbeat();
	emitSocketHeartbeat();
	socketHeartbeatInterval = setInterval(() => {
		emitSocketHeartbeat();
	}, SOCKET_HEARTBEAT_INTERVAL_MS);
};

const ensureRealtimeConnection = async ({ timeoutMs = 4000 } = {}) => {
	if (socket?.connected || getAppState().socketConnected) {
		return true;
	}

	if (!getAppState().deviceToken) {
		return false;
	}

	connectSocket();

	const startedAt = Date.now();
	while (Date.now() - startedAt < timeoutMs) {
		if (socket?.connected || getAppState().socketConnected) {
			return true;
		}
		await sleep(100);
	}

	return Boolean(socket?.connected || getAppState().socketConnected);
};

const connectSocket = () => {
	const { deviceToken } = getAppState();
	if (!deviceToken) return;

	stopSocketHeartbeat();
	if (socket) socket.disconnect();
	socket = io(getBackendUrl(), {
		auth: { token: deviceToken },
		withCredentials: true
	});

	socket.on('connect', () => {
		startSocketHeartbeat();
		setAppState({ socketConnected: true });
		addActivity('System', 'Connected to realtime server');
		if (getAppState().device?.role === 'camera') {
			void startCameraPreview();
		}
		applyMotionDetectionReadiness();
	});

	socket.on('disconnect', () => {
		stopSocketHeartbeat();
		setAppState({ socketConnected: false });
		void stopLocalRecording();
		teardownPeerConnection();
		setAppState({ activeCameraDeviceId: null, activeStreamSessionId: null });
		applyMotionDetectionReadiness();
	});

	socket.on('connect_error', (error) => {
		const message = error?.message || 'Realtime connection failed';
		stopSocketHeartbeat();
		setAppState({ socketConnected: false });
		addActivity('System', `Realtime connection failed: ${message}`);

		if (INVALID_DEVICE_TOKEN_ERRORS.has(message)) {
			void invalidateSavedDevice('Saved device is invalid for this account. Please register this browser again.');
			return;
		}

		pushToast(message, 'error');
		applyMotionDetectionReadiness();
	});

	socket.on('command:received', async (payload) => {
		addActivity('Command', `Received ${payload.commandType}`);

		try {
			if (payload.commandType === 'start_stream') {
				await handleCameraStreamRequest({
					streamId: payload.payload.streamSessionId,
					requesterDeviceId: payload.sourceDeviceId
				});
				socket.emit('command:ack', { commandId: payload.commandId, status: 'acknowledged' });
			}
		} catch (error) {
			socket.emit('command:ack', { commandId: payload.commandId, status: 'rejected', error: error.message });
		}
	});

	socket.on('stream:requested', async (payload) => {
		if (getAppState().device?.role !== 'camera') return;

		try {
			await handleCameraStreamRequest({
				streamId: payload.streamSessionId,
				requesterDeviceId: payload.requesterDeviceId
			});
		} catch (error) {
			console.error('Failed handling direct stream request', error);
			pushToast(error.message || 'Failed to accept stream request', 'error');
		}
	});

	socket.on('motion:detected', (payload) => {
		const cameraDeviceId = payload.cameraDeviceId || payload.deviceId;
		addActivity('Motion', `${getCameraLabel(cameraDeviceId)} has detected movement`);
		pushToast('Motion Detected!', 'info');
		pushMotionNotification(cameraDeviceId);

		if (cameraDeviceId) {
			setAppState({ activeCameraDeviceId: cameraDeviceId });
			void actions.requestStream(cameraDeviceId);
		}
	});

	socket.on('stream:started', async (payload) => {
		addActivity('Stream', 'Stream is live, connecting...');

		const currentState = getAppState();
		const cameraSessions = { ...currentState.cameraSessions, [payload.cameraDeviceId]: payload.streamSessionId };
		setAppState({ cameraSessions });

		if (payload.cameraDeviceId === currentState.activeCameraDeviceId) {
			setAppState({ activeStreamSessionId: payload.streamSessionId });
			if (remoteStreams.has(payload.streamSessionId)) {
				attachClientStreamToElement();
				setClientStreamMode('video');
			} else {
				setClientStreamMode('connecting');
			}
		}

		streamTimers.set(
			payload.streamSessionId,
			setTimeout(() => {
				if (!remoteStreams.has(payload.streamSessionId)) {
					addActivity('Stream', `No remote video track received for ${payload.streamSessionId}`);
					if (getAppState().activeStreamSessionId === payload.streamSessionId) {
						setClientStreamMode('unavailable');
					}
				}
			}, 6000)
		);
	});

	socket.on('stream:ended', async (payload) => {
		if (!payload?.streamSessionId) return;
		const streamSessionId = payload.streamSessionId;

		teardownPeerConnection(streamSessionId);
		if (streamSessionId === getAppState().activeStreamSessionId) {
			setAppState({ activeStreamSessionId: null });
		}

		if (getAppState().device?.role === 'camera') {
			const shouldFinalize =
				activeRecordingStreamSessionId === streamSessionId || activeMediaRecorder?.state === 'recording';

			if (shouldFinalize) {
				const captureResult = await stopLocalRecording();
				await finalizeRecordingForStream(streamSessionId, captureResult);
			}

			if (activeRecordingStreamSessionId === streamSessionId) {
				activeRecordingStreamSessionId = null;
			}
		}
	});

	socket.on('webrtc:signal', async (payload) => {
		const device = getAppState().device;
		if (!device || !payload?.streamSessionId || !payload?.signalType || !payload?.fromDeviceId) return;

		try {
			if (payload.signalType === 'offer') {
				if (device.role !== 'client') return;
				addActivity('WebRTC', 'Offer received');
				const connection = await ensurePeerConnection({
					streamSessionId: payload.streamSessionId,
					targetDeviceId: payload.fromDeviceId,
					asCamera: false
				});
				await connection.setRemoteDescription(new RTCSessionDescription(payload.data));
				await applyQueuedCandidates(connection, payload.streamSessionId, payload.fromDeviceId);
				const answer = await connection.createAnswer();
				await connection.setLocalDescription(answer);
				socket.emit('webrtc:signal', {
					toDeviceId: payload.fromDeviceId,
					streamSessionId: payload.streamSessionId,
					signalType: 'answer',
					data: answer
				});
				addActivity('WebRTC', 'Answer sent');
				return;
			}

			if (payload.signalType === 'answer') {
				const connection = peerConnections.get(payload.streamSessionId);
				if (device.role !== 'camera' || !connection) return;

				if (connection.signalingState !== 'have-local-offer') {
					if (connection.signalingState === 'stable' && connection.remoteDescription?.type === 'answer') {
						return;
					}
					return;
				}
				await connection.setRemoteDescription(new RTCSessionDescription(payload.data));
				await applyQueuedCandidates(connection, payload.streamSessionId, payload.fromDeviceId);
				addActivity('WebRTC', 'Answer received and applied');
				return;
			}

			if (payload.signalType === 'candidate') {
				if (!payload.data) return;
				const connection = peerConnections.get(payload.streamSessionId);
				if (!connection || !connection.remoteDescription) {
					queueRemoteCandidate(payload);
					return;
				}
				await connection.addIceCandidate(new RTCIceCandidate(payload.data));
				return;
			}

			if (payload.signalType === 'hangup') {
				teardownPeerConnection(payload.streamSessionId);
				if (getAppState().activeStreamSessionId === payload.streamSessionId) {
					setAppState({ activeStreamSessionId: null });
				}
				addActivity('Stream', 'Remote stream ended');
			}
		} catch (error) {
			console.error('Failed handling WebRTC signal', error);
			pushToast('WebRTC negotiation failed', 'error');
		}
	});

	socket.on('error:webrtc_signal', (payload) => {
		const message = payload?.message || 'WebRTC signaling error';
		addActivity('WebRTC', message);
		pushToast(message, 'error');
	});
};

const stopPolling = () => {
	if (pollInterval) {
		clearInterval(pollInterval);
		pollInterval = null;
	}
};

const pollClientData = async () => {
	const { device } = getAppState();
	if (!device || device.role !== 'client') return;

	const [recs, links, deviceList, notifications] = await Promise.all([
		api.ops.listRecordings().catch(() => ({ recordings: [] })),
		api.devices.listLinks().catch(() => ({ links: [] })),
		api.devices.list().catch(() => ({ devices: [] })),
		api.ops.listNotifications().catch(() => ({ notifications: [] }))
	]);

	const cameraById = new Map(
		(deviceList.devices || [])
			.filter((entry) => entry.role === 'camera')
			.map((entry) => [entry.id, entry])
	);

	const linkedCameras = (links.links || []).map((link) => {
		const camera = cameraById.get(link.cameraDeviceId);
		return {
			...link,
			cameraName: camera?.name ?? null,
			cameraStatus: camera?.status ?? 'offline'
		};
	});

	setAppState({
		recordings: recs.recordings || [],
		linkedCameras
	});
	syncMotionNotificationsFromDeliveries(notifications.notifications);
};

const startPolling = () => {
	stopPolling();
	void pollClientData();
	pollInterval = setInterval(() => {
		void pollClientData();
	}, 5000);
};

const cleanupConnectionState = async () => {
	stopPolling();
	stopSocketHeartbeat();
	await stopLocalRecording();
	teardownPeerConnection();
	stopCameraPreview();
	if (motionDetector?.isRunning()) {
		motionDetector.stop('idle');
	}
	if (socket) {
		socket.disconnect();
		socket = null;
	}
	requestedStreams.clear();
};

const invalidateSavedDevice = async (message, options = {}) => {
	const { showToast = true } = options;
	clearSavedDeviceRecord();
	await cleanupConnectionState();
	clearDeviceState();
	if (showToast) {
		pushToast(message || 'Saved device is no longer valid. Please register this browser again.', 'error');
	}
	navigateToScreen('onboarding', { replace: true });
};

const enforceRouteForSession = () => {
	const state = getAppState();
	const page = pageFromPath(window.location.pathname);
	setAppState({ page });

	if (!state.session) {
		if (page !== 'auth') {
			navigateToScreen('auth', { replace: true });
		}
		return;
	}

	if (!state.deviceToken) {
		if (page !== 'onboarding') {
			navigateToScreen('onboarding', { replace: true });
		}
		return;
	}

	const expectedHome = getHomePageKeyForRole(state.device?.role);
	if ((page === 'auth' || page === 'onboarding') && expectedHome) {
		navigateToScreen('home', { replace: true, role: state.device?.role });
		return;
	}

	if ((page === 'camera' || page === 'client') && page !== expectedHome) {
		navigateToScreen('home', { replace: true, role: state.device?.role });
	}
};

const init = async () => {
	if (initialized) return;
	if (initPromise) return initPromise;

	initPromise = (async () => {
		setAppState({ page: pageFromPath(window.location.pathname), loading: true });
		if (navigator.mediaDevices?.addEventListener) {
			navigator.mediaDevices.addEventListener('devicechange', onMediaDeviceChange);
		}
		if (typeof document !== 'undefined') {
			document.addEventListener('visibilitychange', onVisibilityChange);
		}

		setAppState({ motionDetection: loadMotionDetectionSettings() });

		try {
			const session = await api.auth.getSession();
			if (session?.session) {
				setAppState({ session });
				const restoredSavedDevice = await restoreSavedDeviceForSession(session);
				if (restoredSavedDevice) {
					connectSocket();
					startPolling();
				}
			} else {
				setAppState({ session: null });
				clearDeviceState();
			}
		} catch {
			setAppState({ session: null });
			clearDeviceState();
		}

		enforceRouteForSession();
		void refreshCameraInputDevices();
		applyMotionDetectionReadiness();

		window.addEventListener('beforeunload', () => {
			void cleanupConnectionState();
		});

		initialized = true;
	})().finally(() => {
		setAppState({ loading: false });
		initPromise = null;
	});

	return initPromise;
};

const destroy = async () => {
	if (navigator.mediaDevices?.removeEventListener) {
		navigator.mediaDevices.removeEventListener('devicechange', onMediaDeviceChange);
	}
	if (typeof document !== 'undefined') {
		document.removeEventListener('visibilitychange', onVisibilityChange);
	}
	initialized = false;
	await cleanupConnectionState();
};

const actions = {
	setPage(page) {
		setAppState({ page });
		if (page === 'activity') {
			markAllNotificationsRead();
		}
		if (page === 'client') {
			void pollClientData();
		}
	},

	navigate(target) {
		if (target === 'activity') {
			markAllNotificationsRead();
		}
		navigateToScreen(target);
	},

	setAuthField(field, value) {
		patchAppState((state) => ({
			authForm: { ...state.authForm, [field]: value }
		}));
	},

	toggleAuthMode() {
		patchAppState((state) => ({ isRegistering: !state.isRegistering }));
	},

	async submitAuth() {
		const state = getAppState();
		const { email, password, name } = state.authForm;
		const normalizedName = name || email.split('@')[0];

		try {
			if (state.isRegistering) {
				await api.auth.signUp({ email, password, name: normalizedName });
			}
			await api.auth.signIn({ email, password });
			const session = await api.auth.getSession();
			setAppState({ session, authForm: { ...state.authForm, password: '' } });
			pushToast(`Welcome, ${session.user.name}`, 'success');

			const restoredSavedDevice = await restoreSavedDeviceForSession(session);
			if (restoredSavedDevice) {
				connectSocket();
				startPolling();
				navigateToScreen('home', { role: getAppState().device?.role });
			} else {
				navigateToScreen('onboarding');
			}
		} catch (error) {
			pushToast(error.message || 'Authentication failed', 'error');
		}
	},

	setOnboardingField(field, value) {
		patchAppState((state) => ({
			onboardingForm: { ...state.onboardingForm, [field]: value }
		}));
	},

	selectRole(role) {
		patchAppState((state) => ({
			onboardingForm: { ...state.onboardingForm, role }
		}));
	},

	async registerDevice() {
		const { onboardingForm } = getAppState();
		const name = onboardingForm.name || 'Web Dashboard';
		const role = onboardingForm.role;
		const pushToken = onboardingForm.pushToken;

		try {
			const payload = { name, role, platform: 'web', appVersion: 'webapp-1.0' };
			if (pushToken?.trim()) {
				payload.pushToken = pushToken.trim();
			}

			const result = await api.devices.register(payload);
			applySavedDeviceState(result.device, result.deviceToken);
			persistSavedDeviceRecord({
				device: result.device,
				deviceToken: result.deviceToken,
				userId: getAppState().session?.user?.id ?? null
			});

			pushToast('Device Registered', 'success');
			connectSocket();
			startPolling();
			navigateToScreen('home', { role: result.device.role });
		} catch (error) {
			pushToast(error.message || 'Device registration failed', 'error');
		}
	},

	loadSavedDevice() {
		const session = getAppState().session;
		if (!session) {
			pushToast('Please sign in before loading a saved device', 'error');
			return;
		}

		void restoreSavedDeviceForSession(session, { showMissingToast: true, showInvalidToast: true }).then((restored) => {
			if (restored) {
				pushToast('Loaded saved device', 'success');
			}
		});
	},

	async signOut() {
		try {
			await api.auth.signOut();
		} catch {
			// ignore
		}

		await cleanupConnectionState();
		clearSavedDeviceRecord();
		const keep = { page: 'auth', toasts: [] };
		resetAppState(keep);
		pushToast('Signed Out', 'info');
		navigateToScreen('auth', { replace: true });
	},

	async startMotion() {
		try {
			await startMotionEvent({ source: 'manual' });
		} catch (error) {
			pushToast(error.message || 'Failed to start motion', 'error');
		}
	},

	async endMotion() {
		if (!lastMotionEventId) return;
		try {
			await endMotionEvent({ source: 'manual' });
		} catch (error) {
			pushToast(error.message || 'Failed to end motion', 'error');
		}
	},

	async goOnline() {
		await startCameraPreview();
		connectSocket();
	},

	async refreshCameraInputs(showToast = true) {
		const inputs = await refreshCameraInputDevices();
		if (!showToast) return;
		if (inputs.length === 0) {
			pushToast('No camera inputs detected', 'info');
			return;
		}
		pushToast('Camera list refreshed', 'success');
	},

	async selectCameraInput(cameraInputId) {
		const nextCameraInputId = typeof cameraInputId === 'string' ? cameraInputId.trim() : '';
		if (!nextCameraInputId) return;

		setAppState({ selectedCameraInputId: nextCameraInputId });
		const isPreviewRunning = Boolean(localCameraStream);
		if (!isPreviewRunning) return;

		const ready = await startCameraPreview(nextCameraInputId);
		if (!ready) {
			pushToast('Failed to switch camera', 'error');
		}
	},

	setMotionDetectionEnabled(enabled) {
		const motionDetection = updateMotionDetectionState({ enabled: Boolean(enabled) });
		pushToast(motionDetection.enabled ? 'Automatic detection armed' : 'Automatic detection paused', 'info');
		addActivity('Motion Detection', motionDetection.enabled ? 'Detector armed' : 'Detector paused');
		applyMotionDetectionReadiness();
	},

	setMotionDetectionProfile(profile) {
		const nextProfile = getMotionDetectionProfile(profile);
		const motionDetection = updateMotionDetectionState({ profile: nextProfile.profile });
		pushToast(`${nextProfile.label} profile selected`, 'success');
		addActivity('Motion Detection', `Profile set to ${motionDetection.profile}`);
		applyMotionDetectionReadiness();
	},

	setMotionDetectionDebug(debug) {
		const motionDetection = updateMotionDetectionState({ debug: Boolean(debug) });
		pushToast(motionDetection.debug ? 'Motion debug enabled' : 'Motion debug hidden', 'info');
	},

	async linkCamera() {
		const id = prompt('Enter Camera Device ID:');
		if (!id) return;
		try {
			await api.devices.link(id, getAppState().device.id);
			pushToast('Camera Linked', 'success');
			await pollClientData();
		} catch (error) {
			pushToast(error.message || 'Failed to link camera', 'error');
		}
	},

	toggleLinkedCameraMenu(linkId) {
		patchAppState((state) => ({
			openLinkedCameraMenuId: state.openLinkedCameraMenuId === linkId ? null : linkId
		}));
	},

	closeLinkedCameraMenu() {
		setAppState({ openLinkedCameraMenuId: null });
	},

	async renameLinkedCamera(cameraDeviceId) {
		const linked = getLinkedCamera(cameraDeviceId);
		if (!linked?.cameraDeviceId) return;

		const currentName = linked.cameraName?.trim() || '';
		const nextName = prompt('Enter a new camera name:', currentName || getCameraLabel(linked.cameraDeviceId));
		if (nextName == null) return;

		const trimmedName = nextName.trim();
		if (!trimmedName) {
			pushToast('Camera name cannot be empty', 'error');
			return;
		}
		if (trimmedName === currentName) return;

		try {
			await api.devices.update(linked.cameraDeviceId, { name: trimmedName });
			patchAppState((state) => ({
				linkedCameras: state.linkedCameras.map((entry) =>
					entry.cameraDeviceId === linked.cameraDeviceId ? { ...entry, cameraName: trimmedName } : entry
				),
				openLinkedCameraMenuId: null
			}));
			pushToast('Camera Renamed', 'success');
		} catch (error) {
			pushToast(error.message || 'Failed to rename camera', 'error');
		}
	},

	async deleteLinkedCamera(linkId) {
		const link = getAppState().linkedCameras.find((entry) => entry.id === linkId);
		if (!link) return;

		const cameraLabel = getCameraLabel(link.cameraDeviceId, link.cameraName);
		const confirmed = window.confirm(`Remove "${cameraLabel}" from linked cameras?`);
		if (!confirmed) return;

		try {
			await api.devices.unlink(linkId);
			const remaining = getAppState().linkedCameras.filter((entry) => entry.id !== linkId);
			const isDeletedCameraActive = getAppState().activeCameraDeviceId === link.cameraDeviceId;
			if (isDeletedCameraActive) {
				clearClientStream();
			}
			requestedStreams.delete(link.cameraDeviceId);

			setAppState({
				linkedCameras: remaining,
				activeCameraDeviceId: isDeletedCameraActive ? null : getAppState().activeCameraDeviceId,
				activeStreamSessionId: isDeletedCameraActive ? null : getAppState().activeStreamSessionId,
				openLinkedCameraMenuId: null
			});

			pushToast('Camera Link Removed', 'success');
		} catch (error) {
			pushToast(error.message || 'Failed to remove camera link', 'error');
		}
	},

	async requestStream(cameraDeviceId) {
		const realtimeReady = await ensureRealtimeConnection();
		if (!realtimeReady) {
			pushToast('Realtime connection unavailable. Reconnect and try again.', 'error');
			return;
		}

		try {
			requestedStreams.add(cameraDeviceId);
			await api.streams.request(cameraDeviceId);
		} catch (error) {
			requestedStreams.delete(cameraDeviceId);
			pushToast(error.message || 'Failed to request stream', 'error');
		}
	},

	async selectCamera(cameraDeviceId) {
		const currentState = getAppState();
		const sessions = currentState.cameraSessions || {};
		const existingSessionId = sessions[cameraDeviceId] || null;
		const reusableSessionId = hasReusableClientStreamSession(existingSessionId) ? existingSessionId : null;
		const previousActiveStreamSessionId = currentState.activeStreamSessionId;
		const isSwitchingStreams =
			Boolean(previousActiveStreamSessionId) && previousActiveStreamSessionId !== reusableSessionId;

		if (currentState.activeCameraDeviceId !== cameraDeviceId || currentState.activeStreamSessionId !== reusableSessionId) {
			clearClientStream();
		}

		setAppState({
			activeCameraDeviceId: cameraDeviceId,
			activeStreamSessionId: reusableSessionId,
			openLinkedCameraMenuId: null
		});

		if (isSwitchingStreams) {
			void endClientStreamSession(previousActiveStreamSessionId, { teardown: false });
		}

		if (reusableSessionId) {
			attachClientStreamToElement();
			setClientStreamMode(remoteStreams.has(reusableSessionId) ? 'video' : 'connecting');
			return;
		}

		setClientStreamMode('connecting');
		await actions.requestStream(cameraDeviceId);
	},

	closeStreamViewer() {
		const streamSessionId = getAppState().activeStreamSessionId;
		setAppState({ activeCameraDeviceId: null, activeStreamSessionId: null });
		clearClientStream();
		void endClientStreamSession(streamSessionId, { teardown: false });
	},

	async openRecording(recordingId) {
		try {
			const result = await api.ops.getRecordingDownloadUrl(recordingId);
			if (!result?.downloadUrl) {
				pushToast('Recording URL unavailable', 'error');
				return;
			}
			const recording = getAppState().recordings.find((entry) => entry.id === recordingId);
			const title = recording
				? `${new Date(recording.createdAt).toLocaleString()} recording`
				: 'Recording Playback';
			openRecordingModal(result.downloadUrl, title);
		} catch (error) {
			pushToast(error.message || 'Failed to load recording', 'error');
		}
	},

	closeRecordingModal() {
		closeRecordingModal();
	},

	async openMotionNotificationTarget(notificationId, cameraDeviceId) {
		await markMotionNotificationRead(notificationId);
		if (!cameraDeviceId) return;

		const recs = await api.ops.listRecordings().catch(() => ({ recordings: [] }));
		const readyRecording = (recs.recordings || [])
			.filter((recording) => recording.cameraDeviceId === cameraDeviceId && recording.status === 'ready')
			.sort((left, right) => new Date(right.createdAt).getTime() - new Date(left.createdAt).getTime())[0];

		if (readyRecording?.id) {
			await actions.openRecording(readyRecording.id);
			return;
		}

		navigateToScreen('home', { role: getAppState().device?.role });
		await actions.requestStream(cameraDeviceId);
	},

	markAllNotificationsRead() {
		void markAllNotificationsRead();
	},

	clearNotifications() {
		patchAppState((state) => ({
			motionNotifications: state.motionNotifications.filter((notification) => !notification.isRead)
		}));
	},

	refreshClientData() {
		void pollClientData();
	},

	runDiagnostics() {
		pushToast('Diagnostics complete: realtime connected', 'success');
	},

	removeToast,

	setCameraVideoElement(element) {
		cameraVideoElement = element;
		attachCameraStreamToElement();
		void refreshCameraInputDevices();
	},

	setClientVideoElement(element) {
		clientVideoElement = element;
		attachClientStreamToElement();
	}
};

export const appController = {
	init,
	destroy,
	...actions
};
