<script lang="ts">
	// DiffView — Zeigt Unterschiede zwischen altem und neuem Code
	// Mit optionalen Accept/Reject-Buttons fuer interaktiven Modus

	interface Props {
		oldText: string;
		newText: string;
		filename?: string;
		language?: string;
		interactive?: boolean;
		toolId?: string;
		onAccept?: (toolId: string) => void;
		onReject?: (toolId: string) => void;
	}

	let {
		oldText,
		newText,
		filename = '',
		language = '',
		interactive = false,
		toolId = '',
		onAccept,
		onReject,
	}: Props = $props();

	// Einfache Diff-Berechnung (zeilenbasiert)
	interface DiffLine {
		type: 'unchanged' | 'added' | 'removed';
		lineNo: { old: number | null; new: number | null };
		text: string;
	}

	function computeDiff(oldStr: string, newStr: string): DiffLine[] {
		const oldLines = oldStr.split('\n');
		const newLines = newStr.split('\n');
		const result: DiffLine[] = [];

		// Einfacher LCS-basierter Diff
		const lcs = longestCommonSubsequence(oldLines, newLines);
		let oldIdx = 0;
		let newIdx = 0;
		let lcsIdx = 0;

		while (oldIdx < oldLines.length || newIdx < newLines.length) {
			if (lcsIdx < lcs.length && oldIdx < oldLines.length && oldLines[oldIdx] === lcs[lcsIdx]) {
				// Unveraenderte Zeile
				if (newIdx < newLines.length && newLines[newIdx] === lcs[lcsIdx]) {
					result.push({
						type: 'unchanged',
						lineNo: { old: oldIdx + 1, new: newIdx + 1 },
						text: oldLines[oldIdx]
					});
					oldIdx++;
					newIdx++;
					lcsIdx++;
				} else {
					// Neue Zeile hinzugefuegt
					result.push({
						type: 'added',
						lineNo: { old: null, new: newIdx + 1 },
						text: newLines[newIdx]
					});
					newIdx++;
				}
			} else if (oldIdx < oldLines.length && (lcsIdx >= lcs.length || oldLines[oldIdx] !== lcs[lcsIdx])) {
				// Zeile entfernt
				result.push({
					type: 'removed',
					lineNo: { old: oldIdx + 1, new: null },
					text: oldLines[oldIdx]
				});
				oldIdx++;
			} else if (newIdx < newLines.length) {
				// Zeile hinzugefuegt
				result.push({
					type: 'added',
					lineNo: { old: null, new: newIdx + 1 },
					text: newLines[newIdx]
				});
				newIdx++;
			}
		}

		return result;
	}

	function longestCommonSubsequence(a: string[], b: string[]): string[] {
		const m = a.length;
		const n = b.length;
		const dp: number[][] = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));

		for (let i = 1; i <= m; i++) {
			for (let j = 1; j <= n; j++) {
				if (a[i - 1] === b[j - 1]) {
					dp[i][j] = dp[i - 1][j - 1] + 1;
				} else {
					dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
				}
			}
		}

		// Backtrack um LCS zu rekonstruieren
		const result: string[] = [];
		let i = m, j = n;
		while (i > 0 && j > 0) {
			if (a[i - 1] === b[j - 1]) {
				result.unshift(a[i - 1]);
				i--;
				j--;
			} else if (dp[i - 1][j] > dp[i][j - 1]) {
				i--;
			} else {
				j--;
			}
		}

		return result;
	}

	// Diff berechnen wenn sich Inputs aendern
	let diffLines = $derived(computeDiff(oldText, newText));

	// Statistiken
	let stats = $derived({
		added: diffLines.filter(l => l.type === 'added').length,
		removed: diffLines.filter(l => l.type === 'removed').length,
		unchanged: diffLines.filter(l => l.type === 'unchanged').length,
	});

	// Nur geaenderte Zeilen anzeigen mit Kontext (3 Zeilen davor/danach)
	let showFullDiff = $state(false);
	let contextLines = 3;

	function getVisibleLines(): { line: DiffLine; idx: number }[] {
		if (showFullDiff) return diffLines.map((line, idx) => ({ line, idx }));

		const changedIndices = new Set<number>();
		diffLines.forEach((line, idx) => {
			if (line.type !== 'unchanged') {
				for (let i = Math.max(0, idx - contextLines); i <= Math.min(diffLines.length - 1, idx + contextLines); i++) {
					changedIndices.add(i);
				}
			}
		});

		return Array.from(changedIndices).sort((a, b) => a - b).map(idx => ({ line: diffLines[idx], idx }));
	}

	let visibleLines = $derived(getVisibleLines());

	function handleAccept() {
		if (onAccept && toolId) onAccept(toolId);
	}

	function handleReject() {
		if (onReject && toolId) onReject(toolId);
	}

	// Dateiname kuerzen fuer Anzeige
	function shortenPath(path: string): string {
		const parts = path.split('/');
		if (parts.length > 3) return `.../${parts.slice(-2).join('/')}`;
		return path;
	}
</script>

<div class="diff-view" class:interactive>
	<div class="diff-header">
		<div class="diff-header-left">
			{#if filename}
				<span class="filename" title={filename}>{shortenPath(filename)}</span>
			{/if}
			{#if language}
				<span class="language">{language}</span>
			{/if}
			<span class="stats">
				<span class="stat-added">+{stats.added}</span>
				<span class="stat-removed">-{stats.removed}</span>
			</span>
		</div>
		<div class="diff-header-right">
			{#if diffLines.length > 20}
				<button class="btn-toggle" onclick={() => showFullDiff = !showFullDiff}>
					{showFullDiff ? 'Kompakt' : 'Alles zeigen'}
				</button>
			{/if}
			{#if interactive}
				<button class="btn-accept" onclick={handleAccept} title="Diese Aenderung auf die Datei anwenden (Ctrl+Enter)">
					✓ Übernehmen
				</button>
				<button class="btn-reject" onclick={handleReject} title="Aenderung verwerfen, Datei bleibt unveraendert (Ctrl+Backspace)">
					✕ Verwerfen
				</button>
			{/if}
		</div>
	</div>

	<div class="diff-content">
		{#each visibleLines as { line, idx } (idx)}
			{@const prevIdx = visibleLines[visibleLines.indexOf({ line, idx }) - 1]?.idx}
			{#if idx > 0 && prevIdx !== undefined && idx - prevIdx > 1}
				<div class="diff-separator">⋯</div>
			{/if}
			<div class="diff-line" class:added={line.type === 'added'} class:removed={line.type === 'removed'}>
				<span class="line-no old">{line.lineNo.old ?? ''}</span>
				<span class="line-no new">{line.lineNo.new ?? ''}</span>
				<span class="line-marker">
					{#if line.type === 'added'}+{:else if line.type === 'removed'}-{:else}{/if}
				</span>
				<span class="line-text">{line.text || '\u00A0'}</span>
			</div>
		{/each}
	</div>
</div>

<style>
	.diff-view {
		font-family: var(--font-mono);
		font-size: 0.75rem;
		border: 1px solid var(--border);
		border-radius: var(--radius-sm);
		overflow: hidden;
	}

	.diff-view.interactive {
		border-color: var(--accent);
		box-shadow: 0 0 0 1px var(--accent), 0 2px 8px rgba(0, 0, 0, 0.2);
	}

	.diff-header {
		display: flex;
		align-items: center;
		justify-content: space-between;
		padding: var(--spacing-xs) var(--spacing-sm);
		background: var(--bg-secondary);
		border-bottom: 1px solid var(--border);
		gap: var(--spacing-sm);
	}

	.diff-header-left {
		display: flex;
		align-items: center;
		gap: var(--spacing-sm);
		min-width: 0;
		flex: 1;
	}

	.diff-header-right {
		display: flex;
		align-items: center;
		gap: var(--spacing-xs);
		flex-shrink: 0;
	}

	.filename {
		font-weight: 600;
		color: var(--text-primary);
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
	}

	.language {
		font-size: 0.65rem;
		padding: 1px 4px;
		background: var(--bg-tertiary);
		border-radius: 2px;
		color: var(--text-secondary);
	}

	.stats {
		display: flex;
		gap: var(--spacing-xs);
		font-size: 0.7rem;
	}

	.stat-added { color: var(--success); }
	.stat-removed { color: var(--error); }

	.btn-toggle {
		padding: 2px 6px;
		font-size: 0.6rem;
		background: var(--bg-tertiary);
		border: 1px solid var(--border);
		border-radius: var(--radius-sm);
		color: var(--text-secondary);
		cursor: pointer;
	}

	.btn-toggle:hover {
		background: var(--bg-hover);
		color: var(--text-primary);
	}

	.btn-accept {
		padding: 2px 8px;
		font-size: 0.65rem;
		background: rgba(34, 197, 94, 0.15);
		border: 1px solid var(--success);
		border-radius: var(--radius-sm);
		color: var(--success);
		cursor: pointer;
		font-weight: 600;
		transition: all 0.15s;
	}

	.btn-accept:hover {
		background: var(--success);
		color: white;
	}

	.btn-reject {
		padding: 2px 8px;
		font-size: 0.65rem;
		background: rgba(239, 68, 68, 0.1);
		border: 1px solid var(--error);
		border-radius: var(--radius-sm);
		color: var(--error);
		cursor: pointer;
		font-weight: 600;
		transition: all 0.15s;
	}

	.btn-reject:hover {
		background: var(--error);
		color: white;
	}

	.diff-content {
		overflow-x: auto;
		max-height: 400px;
		overflow-y: auto;
	}

	.diff-line {
		display: flex;
		line-height: 1.5;
		white-space: pre;
	}

	.diff-line.added {
		background: rgba(34, 197, 94, 0.15);
	}

	.diff-line.removed {
		background: rgba(239, 68, 68, 0.15);
	}

	.line-no {
		width: 32px;
		text-align: right;
		padding-right: var(--spacing-xs);
		color: var(--text-secondary);
		opacity: 0.5;
		user-select: none;
		flex-shrink: 0;
	}

	.line-marker {
		width: 16px;
		text-align: center;
		flex-shrink: 0;
		font-weight: bold;
	}

	.diff-line.added .line-marker {
		color: var(--success);
	}

	.diff-line.removed .line-marker {
		color: var(--error);
	}

	.line-text {
		flex: 1;
		padding-left: var(--spacing-xs);
	}

	.diff-separator {
		text-align: center;
		padding: 2px 0;
		color: var(--text-secondary);
		background: var(--bg-tertiary);
		font-size: 0.6rem;
		user-select: none;
	}
</style>
