<script lang="ts">
	import { uploadMedia } from '$lib/api';

	interface Props {
		accessToken?: string;
		/** Called when upload completes. Returns media_node_id + cas_hash. */
		onrecorded?: (result: { media_node_id: string; cas_hash: string }) => void;
		/** Called on error */
		onerror?: (message: string) => void;
		/** Optional context node to attach media to */
		sourceId?: string;
		disabled?: boolean;
		/** Max recording duration in seconds (default: 300 = 5 min) */
		maxDuration?: number;
	}

	let {
		accessToken,
		onrecorded,
		onerror,
		sourceId,
		disabled = false,
		maxDuration = 300,
	}: Props = $props();

	type RecordingState = 'idle' | 'picking' | 'recording' | 'uploading';
	type RecordMode = 'webcam' | 'screen';

	let recState: RecordingState = $state('idle');
	let mode: RecordMode = $state('webcam');
	let mediaRecorder: MediaRecorder | undefined = $state();
	let stream: MediaStream | undefined = $state();
	let chunks: Blob[] = [];
	let duration = $state(0);
	let durationInterval: ReturnType<typeof setInterval> | undefined;
	let previewEl: HTMLVideoElement | undefined = $state();

	function formatDuration(seconds: number): string {
		const m = Math.floor(seconds / 60);
		const s = seconds % 60;
		return `${m}:${s.toString().padStart(2, '0')}`;
	}

	function showPicker() {
		if (!accessToken) {
			onerror?.('Ikke innlogget — kan ikke ta opp video');
			return;
		}
		recState = 'picking';
	}

	function hidePicker() {
		recState = 'idle';
	}

	async function startRecording(selectedMode: RecordMode) {
		mode = selectedMode;
		recState = 'picking'; // keep UI while acquiring stream

		try {
			if (selectedMode === 'webcam') {
				stream = await navigator.mediaDevices.getUserMedia({
					video: { facingMode: 'user', width: { ideal: 1280 }, height: { ideal: 720 } },
					audio: true,
				});
			} else {
				stream = await navigator.mediaDevices.getDisplayMedia({
					video: { width: { ideal: 1920 }, height: { ideal: 1080 } },
					audio: true,
				});
				// Screen share can be stopped by the browser's own UI
				stream.getVideoTracks()[0]?.addEventListener('ended', () => {
					if (recState === 'recording') stopRecording();
				});
			}
		} catch {
			const msg = selectedMode === 'webcam'
				? 'Ingen tilgang til kamera. Sjekk nettleserinnstillinger.'
				: 'Skjermdeling ble avbrutt eller nektet.';
			onerror?.(msg);
			recState = 'idle';
			return;
		}

		// Show preview
		if (previewEl && stream) {
			previewEl.srcObject = stream;
		}

		chunks = [];
		duration = 0;

		// Prefer webm VP8/VP9
		const mimeType = MediaRecorder.isTypeSupported('video/webm;codecs=vp9,opus')
			? 'video/webm;codecs=vp9,opus'
			: MediaRecorder.isTypeSupported('video/webm;codecs=vp8,opus')
				? 'video/webm;codecs=vp8,opus'
				: MediaRecorder.isTypeSupported('video/webm')
					? 'video/webm'
					: '';

		mediaRecorder = new MediaRecorder(stream, mimeType ? { mimeType } : undefined);

		mediaRecorder.ondataavailable = (e) => {
			if (e.data.size > 0) chunks.push(e.data);
		};

		mediaRecorder.onstop = async () => {
			stopTimer();
			stopStream();

			if (chunks.length === 0) {
				recState = 'idle';
				return;
			}

			const blob = new Blob(chunks, { type: mediaRecorder?.mimeType || 'video/webm' });
			chunks = [];

			recState = 'uploading';
			try {
				const ext = blob.type.includes('mp4') ? 'mp4' : 'webm';
				const prefix = mode === 'webcam' ? 'video-memo' : 'screen-recording';
				const file = new File([blob], `${prefix}.${ext}`, { type: blob.type });

				const result = await uploadMedia(accessToken!, {
					file,
					title: mode === 'webcam' ? 'Videomelding' : 'Skjermopptak',
					visibility: 'hidden',
					source_id: sourceId,
					metadata_extra: {
						source: 'video_recording',
						record_type: mode,
						duration_seconds: duration,
					},
				});

				onrecorded?.({
					media_node_id: result.media_node_id,
					cas_hash: result.cas_hash,
				});
			} catch (e) {
				onerror?.(e instanceof Error ? e.message : 'Feil ved opplasting av video');
			} finally {
				recState = 'idle';
			}
		};

		mediaRecorder.start(1000);
		recState = 'recording';
		startTimer();
	}

	function stopRecording() {
		if (mediaRecorder?.state === 'recording') {
			mediaRecorder.stop();
		}
	}

	function cancelRecording() {
		chunks = [];
		if (mediaRecorder?.state === 'recording') {
			mediaRecorder.stop();
		}
		stopTimer();
		stopStream();
		recState = 'idle';
	}

	function startTimer() {
		durationInterval = setInterval(() => {
			duration++;
			if (duration >= maxDuration) {
				stopRecording();
			}
		}, 1000);
	}

	function stopTimer() {
		if (durationInterval) {
			clearInterval(durationInterval);
			durationInterval = undefined;
		}
	}

	function stopStream() {
		stream?.getTracks().forEach((t) => t.stop());
		stream = undefined;
		if (previewEl) previewEl.srcObject = null;
	}

	const remaining = $derived(maxDuration - duration);
	const isNearLimit = $derived(remaining <= 30);
</script>

{#if recState === 'idle'}
	<button
		onclick={showPicker}
		disabled={disabled || !accessToken}
		class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full text-gray-400 transition-colors hover:bg-purple-50 hover:text-purple-500 disabled:cursor-not-allowed disabled:opacity-40"
		aria-label="Ta opp video"
		title="Ta opp video"
	>
		<!-- Video camera icon -->
		<svg class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
			<path stroke-linecap="round" stroke-linejoin="round" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" />
		</svg>
	</button>

{:else if recState === 'picking'}
	<div class="flex items-center gap-1">
		<!-- Close picker -->
		<button
			onclick={hidePicker}
			class="flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-gray-400 hover:bg-gray-100 hover:text-gray-600"
			aria-label="Avbryt"
			title="Avbryt"
		>
			<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
				<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
			</svg>
		</button>
		<!-- Webcam -->
		<button
			onclick={() => startRecording('webcam')}
			class="flex items-center gap-1 rounded-full bg-purple-100 px-3 py-1.5 text-xs font-medium text-purple-700 hover:bg-purple-200"
			aria-label="Webcam"
			title="Ta opp med kamera"
		>
			<svg class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
				<path stroke-linecap="round" stroke-linejoin="round" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" />
			</svg>
			Kamera
		</button>
		<!-- Screen -->
		<button
			onclick={() => startRecording('screen')}
			class="flex items-center gap-1 rounded-full bg-purple-100 px-3 py-1.5 text-xs font-medium text-purple-700 hover:bg-purple-200"
			aria-label="Skjermopptak"
			title="Ta opp skjermen"
		>
			<svg class="h-3.5 w-3.5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
				<path stroke-linecap="round" stroke-linejoin="round" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
			</svg>
			Skjerm
		</button>
	</div>

{:else if recState === 'recording'}
	<div class="flex items-center gap-2">
		<!-- Small preview -->
		<div class="relative h-12 w-16 overflow-hidden rounded border border-gray-200 bg-black">
			<video
				bind:this={previewEl}
				autoplay
				muted
				playsinline
				class="h-full w-full object-cover"
			></video>
		</div>

		<!-- Cancel button -->
		<button
			onclick={cancelRecording}
			class="flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-gray-400 hover:bg-gray-100 hover:text-gray-600"
			aria-label="Avbryt opptak"
			title="Avbryt opptak"
		>
			<svg class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
				<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
			</svg>
		</button>

		<!-- Recording indicator + duration -->
		<div class="flex items-center gap-1.5">
			<span class="h-2 w-2 animate-pulse rounded-full bg-red-500"></span>
			<span class="text-xs font-medium {isNearLimit ? 'text-orange-600' : 'text-red-600'}">
				{formatDuration(duration)}
			</span>
			{#if isNearLimit}
				<span class="text-[10px] text-orange-500">({formatDuration(remaining)})</span>
			{/if}
		</div>

		<!-- Stop/send button -->
		<button
			onclick={stopRecording}
			class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-red-600 text-white transition-colors hover:bg-red-700"
			aria-label="Stopp og send opptak"
			title="Stopp og send opptak"
		>
			<svg class="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
				<rect x="6" y="6" width="12" height="12" rx="2" />
			</svg>
		</button>
	</div>

{:else if recState === 'uploading'}
	<div class="flex items-center gap-1.5">
		<svg class="h-4 w-4 animate-spin text-purple-600" fill="none" viewBox="0 0 24 24">
			<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
			<path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z"></path>
		</svg>
		<span class="text-xs text-purple-600">Laster opp video…</span>
	</div>
{/if}
