<script lang="ts">
	import { onMount, onDestroy } from 'svelte';
	import WaveSurfer from 'wavesurfer.js';
	import RegionsPlugin from 'wavesurfer.js/dist/plugins/regions.js';
	import type { SilenceRegion } from '$lib/api';

	interface Props {
		src: string;
		onready?: (duration: number) => void;
		ontimeupdate?: (time: number) => void;
	}

	let { src, onready, ontimeupdate }: Props = $props();

	let container: HTMLDivElement | undefined = $state();
	let wavesurfer: WaveSurfer | undefined = $state();
	let regions: RegionsPlugin | undefined = $state();
	let playing = $state(false);
	let currentTime = $state(0);
	let totalDuration = $state(0);
	let ready = $state(false);
	let loadError = $state(false);
	let zoom = $state(50); // pixels per second

	/** Currently selected region (for cut operations) */
	let activeRegion: { id: string; start: number; end: number } | null = $state(null);

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

	export function getActiveRegion() {
		return activeRegion;
	}

	export function clearActiveRegion() {
		if (activeRegion && regions) {
			const r = regions.getRegions().find((reg) => reg.id === activeRegion!.id);
			if (r) r.remove();
			activeRegion = null;
		}
	}

	/** Add cut region overlay (red) */
	export function addCutRegion(startMs: number, endMs: number) {
		if (!regions) return;
		regions.addRegion({
			start: startMs / 1000,
			end: endMs / 1000,
			color: 'rgba(239, 68, 68, 0.25)',
			drag: false,
			resize: false,
		});
	}

	/** Show silence regions as gray overlay */
	export function showSilenceRegions(silenceRegions: SilenceRegion[]) {
		if (!regions) return;
		// Remove old silence markers
		for (const r of regions.getRegions()) {
			if (r.id.startsWith('silence-')) r.remove();
		}
		for (let i = 0; i < silenceRegions.length; i++) {
			const sr = silenceRegions[i];
			regions.addRegion({
				id: `silence-${i}`,
				start: sr.start_ms / 1000,
				end: sr.end_ms / 1000,
				color: 'rgba(156, 163, 175, 0.3)',
				drag: false,
				resize: false,
			});
		}
	}

	/** Clear all regions */
	export function clearAllRegions() {
		if (!regions) return;
		regions.clearRegions();
		activeRegion = null;
	}

	export function seekTo(timeSec: number) {
		if (!wavesurfer || !ready) return;
		wavesurfer.setTime(timeSec);
	}

	export function play() {
		wavesurfer?.play();
	}

	export function pause() {
		wavesurfer?.pause();
	}

	export function togglePlayback() {
		wavesurfer?.playPause();
	}

	export function isPlaying() {
		return playing;
	}

	onMount(() => {
		if (!container) return;

		regions = RegionsPlugin.create();

		wavesurfer = WaveSurfer.create({
			container,
			height: 128,
			waveColor: '#93c5fd',
			progressColor: '#2563eb',
			cursorColor: '#1d4ed8',
			cursorWidth: 2,
			barWidth: 2,
			barGap: 1,
			barRadius: 2,
			normalize: true,
			minPxPerSec: zoom,
			url: src,
			plugins: [regions],
		});

		// Enable drag-to-select region
		regions.enableDragSelection({
			color: 'rgba(59, 130, 246, 0.3)',
		});

		regions.on('region-created', (region) => {
			// Only keep one selection at a time (not cut/silence overlays)
			if (!region.id.startsWith('silence-') && !region.id.startsWith('cut-')) {
				// Remove previous active selection
				if (activeRegion && activeRegion.id !== region.id) {
					const old = regions!.getRegions().find((r) => r.id === activeRegion!.id);
					if (old && !old.id.startsWith('cut-')) old.remove();
				}
				activeRegion = {
					id: region.id,
					start: region.start,
					end: region.end,
				};
			}
		});

		regions.on('region-updated', (region) => {
			if (activeRegion && region.id === activeRegion.id) {
				activeRegion = {
					id: region.id,
					start: region.start,
					end: region.end,
				};
			}
		});

		wavesurfer.on('ready', () => {
			ready = true;
			totalDuration = wavesurfer!.getDuration();
			onready?.(totalDuration);
		});

		wavesurfer.on('timeupdate', (time: number) => {
			currentTime = time;
			ontimeupdate?.(time);
		});

		wavesurfer.on('finish', () => {
			playing = false;
		});

		wavesurfer.on('error', () => {
			loadError = true;
		});

		wavesurfer.on('play', () => {
			playing = true;
		});

		wavesurfer.on('pause', () => {
			playing = false;
		});
	});

	onDestroy(() => {
		wavesurfer?.destroy();
	});

	function handleZoom(newZoom: number) {
		zoom = newZoom;
		wavesurfer?.zoom(newZoom);
	}

	function handleKeydown(e: KeyboardEvent) {
		if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) return;
		if (e.code === 'Space') {
			e.preventDefault();
			togglePlayback();
		}
	}
</script>

<svelte:window onkeydown={handleKeydown} />

<div class="studio-waveform flex flex-col gap-2">
	<!-- Waveform -->
	<div class="overflow-x-auto rounded-lg border border-gray-200 bg-gray-50 p-2">
		{#if loadError}
			<p class="py-8 text-center text-sm text-red-400">Kunne ikke laste lydfilen</p>
		{:else if !ready}
			<div class="flex items-center justify-center py-8">
				<svg class="h-5 w-5 animate-spin text-blue-500" 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="ml-2 text-sm text-gray-400">Laster waveform...</span>
			</div>
		{/if}
		<div bind:this={container} class="w-full" class:hidden={!ready && !loadError}></div>
	</div>

	<!-- Transport + zoom -->
	<div class="flex items-center justify-between">
		<div class="flex items-center gap-2">
			<!-- Play/pause -->
			<button
				onclick={togglePlayback}
				disabled={!ready}
				class="flex h-10 w-10 items-center justify-center rounded-full transition-colors
					{ready ? 'bg-blue-600 text-white hover:bg-blue-700' : 'bg-gray-200 text-gray-400'}
					disabled:cursor-not-allowed"
				aria-label={playing ? 'Pause' : 'Spill av'}
			>
				{#if playing}
					<svg class="h-4 w-4" fill="currentColor" viewBox="0 0 24 24">
						<rect x="6" y="4" width="4" height="16" rx="1" />
						<rect x="14" y="4" width="4" height="16" rx="1" />
					</svg>
				{:else}
					<svg class="h-4 w-4 ml-0.5" fill="currentColor" viewBox="0 0 24 24">
						<path d="M8 5v14l11-7z" />
					</svg>
				{/if}
			</button>

			<!-- Time display -->
			<span class="font-mono text-sm text-gray-600">
				{formatTime(currentTime)} / {formatTime(totalDuration)}
			</span>

			<!-- Selection info -->
			{#if activeRegion}
				<span class="rounded bg-blue-50 px-2 py-0.5 text-xs text-blue-600">
					Markert: {formatTime(activeRegion.start)} - {formatTime(activeRegion.end)}
				</span>
			{/if}
		</div>

		<!-- Zoom -->
		<div class="flex items-center gap-2">
			<span class="text-xs text-gray-400">Zoom</span>
			<input
				type="range"
				min="10"
				max="500"
				bind:value={zoom}
				oninput={() => handleZoom(zoom)}
				class="w-24"
			/>
		</div>
	</div>
</div>
