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

	interface Props {
		accessToken?: string;
		/** Called when upload+transcription is triggered. Returns media_node_id. */
		onrecorded?: (result: { media_node_id: string; cas_hash: string }) => void;
		/** Called on error */
		onerror?: (message: string) => void;
		/** Optional context node (e.g. communication node) to attach media to */
		sourceId?: string;
		disabled?: boolean;
	}

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

	type RecordingState = 'idle' | 'recording' | 'uploading';

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

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

	async function startRecording() {
		if (!accessToken) {
			onerror?.('Ikke innlogget — kan ikke ta opp lyd');
			return;
		}

		try {
			stream = await navigator.mediaDevices.getUserMedia({ audio: true });
		} catch {
			onerror?.('Ingen tilgang til mikrofon. Sjekk nettleserinnstillinger.');
			return;
		}

		chunks = [];
		duration = 0;

		// Prefer webm/opus, fall back to whatever the browser supports
		const mimeType = MediaRecorder.isTypeSupported('audio/webm;codecs=opus')
			? 'audio/webm;codecs=opus'
			: MediaRecorder.isTypeSupported('audio/webm')
				? 'audio/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 || 'audio/webm' });
			chunks = [];

			// Upload
			recState = 'uploading';
			try {
				const ext = blob.type.includes('webm') ? 'webm' : 'ogg';
				const file = new File([blob], `voice-memo.${ext}`, { type: blob.type });

				const result = await uploadMedia(accessToken!, {
					file,
					title: 'Talenotat',
					visibility: 'hidden',
					source_id: sourceId,
				});

				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 lydopptak');
			} finally {
				recState = 'idle';
			}
		};

		mediaRecorder.start(1000); // Collect data every second
		recState = 'recording';
		startTimer();
	}

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

	function cancelRecording() {
		chunks = []; // Clear so onstop won't upload
		if (mediaRecorder?.state === 'recording') {
			mediaRecorder.stop();
		}
		stopTimer();
		stopStream();
		recState = 'idle';
	}

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

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

	function stopStream() {
		stream?.getTracks().forEach(t => t.stop());
		stream = undefined;
	}
</script>

{#if recState === 'idle'}
	<button
		onclick={startRecording}
		disabled={disabled || !accessToken}
		class="flex h-10 w-10 shrink-0 items-center justify-center rounded-full text-gray-400 transition-colors hover:bg-red-50 hover:text-red-500 disabled:cursor-not-allowed disabled:opacity-40"
		aria-label="Ta opp talenotat"
		title="Ta opp talenotat"
	>
		<!-- Microphone 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="M12 1a3 3 0 00-3 3v8a3 3 0 006 0V4a3 3 0 00-3-3z" />
			<path stroke-linecap="round" stroke-linejoin="round" d="M19 10v2a7 7 0 01-14 0v-2" />
			<line x1="12" y1="19" x2="12" y2="23" />
			<line x1="8" y1="23" x2="16" y2="23" />
		</svg>
	</button>
{:else if recState === 'recording'}
	<div class="flex items-center gap-2">
		<!-- 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 -->
		<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 text-red-600">{formatDuration(duration)}</span>
		</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-blue-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-blue-600">Laster opp…</span>
	</div>
{/if}
