import { track } from 'ripple';
import type { Component, PropsWithChildren, PropsWithExtras } from 'ripple';

describe('SVG namespace handling', () => {
	it('should render static SVG elements with correct namespace', () => {
		function App() {
			return <>
				<svg
					xmlns="http://www.w3.org/2000/svg"
					width="24"
					height="24"
					fill="none"
					stroke="currentColor"
				>
					<path d="m14 12 4 4 4-4" />
					<circle cx="12" cy="12" r="4" />
					<rect x="4" y="4" width="16" height="16" />
				</svg>
			</>;
		}

		render(App);

		const svg = container.querySelector('svg');
		const path = container.querySelector('path');
		const circle = container.querySelector('circle');
		const rect = container.querySelector('rect');

		// Verify SVG namespace
		expect(svg).toBeTruthy();
		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');

		// Verify child elements have SVG namespace
		expect(path.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(circle.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(rect.namespaceURI).toBe('http://www.w3.org/2000/svg');

		// Verify attributes are set correctly
		expect(path.getAttribute('d')).toBe('m14 12 4 4 4-4');
		expect(circle.getAttribute('cx')).toBe('12');
		expect(rect.getAttribute('width')).toBe('16');
	});

	it('should render dynamic SVG paths with for loop (original issue)', () => {
		function App() {
			return <>
				const d = [
					'm14 12 4 4 4-4',
					'M18 16V7',
					'm2 16 4.039-9.69a.5.5 0 0 1 .923 0L11 16',
					'M3.304 13h6.392',
				];
				<svg
					xmlns="http://www.w3.org/2000/svg"
					width="24"
					height="24"
					fill="none"
					stroke="currentColor"
				>
					for (const pathData of d) {
						<path d={pathData} />
					}
				</svg>
			</>;
		}

		render(App);

		const svg = container.querySelector('svg');
		const paths = container.querySelectorAll('path');

		// Verify SVG container
		expect(svg).toBeTruthy();
		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');

		// Critical test: dynamic paths should have correct SVG namespace
		expect(paths.length).toBe(4);
		const expectedPaths = [
			'm14 12 4 4 4-4',
			'M18 16V7',
			'm2 16 4.039-9.69a.5.5 0 0 1 .923 0L11 16',
			'M3.304 13h6.392',
		];
		paths.forEach((path, i) => {
			expect(path.namespaceURI).toBe('http://www.w3.org/2000/svg');
			expect(path.getAttribute('d')).toBe(expectedPaths[i]);
		});

		// Verify paths are actually SVG elements (should have getBBox method)
		// Note: getBBox might not work in test environment, so just check namespace
		paths.forEach((path) => {
			expect(path.namespaceURI).toBe('http://www.w3.org/2000/svg');
			expect(path.tagName.toLowerCase()).toBe('path');
		});
	});

	it('should handle mixed static and dynamic SVG elements', () => {
		function App() {
			return <>
				const dynamicPaths = ['M12 2L2 7v10c0 5.55 3.84 10 9 11 5.16-1 9-5.45 9-11V7l-10-5z'];
				<svg
					xmlns="http://www.w3.org/2000/svg"
					width="24"
					height="24"
					fill="none"
					stroke="currentColor"
				>
					<circle cx="12" cy="12" r="10" />
					for (const pathData of dynamicPaths) {
						<path d={pathData} />
					}
					<rect x="4" y="4" width="16" height="16" />
				</svg>
			</>;
		}

		render(App);

		const svg = container.querySelector('svg');
		const circle = container.querySelector('circle');
		const path = container.querySelector('path');
		const rect = container.querySelector('rect');

		// All elements should have SVG namespace
		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(circle.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(path.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(rect.namespaceURI).toBe('http://www.w3.org/2000/svg');

		// Verify content
		expect(path.getAttribute('d')).toBe(
			'M12 2L2 7v10c0 5.55 3.84 10 9 11 5.16-1 9-5.45 9-11V7l-10-5z',
		);
	});

	it('should handle nested SVG groups with for loops', () => {
		function App() {
			return <>
				const items = [
					{ x: '10', y: '10', width: '20', height: '20' },
					{ x: '40', y: '40', width: '20', height: '20' },
				];
				<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">
					<g fill="blue">
						for (const item of items) {
							<rect x={item.x} y={item.y} width={item.width} height={item.height} />
						}
					</g>
				</svg>
			</>;
		}

		render(App);

		const svg = container.querySelector('svg');
		const g = container.querySelector('g');
		const rects = container.querySelectorAll('rect');

		// Verify namespaces
		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(g.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(rects.length).toBe(2);

		rects.forEach((rect) => {
			expect(rect.namespaceURI).toBe('http://www.w3.org/2000/svg');
		});

		// Verify attributes
		expect(rects[0].getAttribute('x')).toBe('10');
		expect(rects[0].getAttribute('y')).toBe('10');
		expect(rects[1].getAttribute('x')).toBe('40');
		expect(rects[1].getAttribute('y')).toBe('40');
	});

	it('should handle SVG class attributes correctly', () => {
		function App() {
			return <>
				let className = 'svg-element';
				const paths = ['M10 10 L20 20'];
				<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" class={className}>
					for (const pathData of paths) {
						<path d={pathData} class="dynamic-path" />
					}
					<circle cx="50" cy="50" r="10" class={className} />
				</svg>
			</>;
		}

		render(App);

		const svg = container.querySelector('svg');
		const path = container.querySelector('path');
		const circle = container.querySelector('circle');

		// Verify namespaces
		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(path.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(circle.namespaceURI).toBe('http://www.w3.org/2000/svg');

		// Verify class attributes work with SVG elements
		expect(svg.getAttribute('class')).toBe('svg-element');
		expect(path.getAttribute('class')).toBe('dynamic-path');
		expect(circle.getAttribute('class')).toBe('svg-element');

		// SVG elements should NOT have className property set
		expect(svg.className).not.toBe('svg-element'); // className is different for SVG
		expect(path.className).not.toBe('dynamic-path');
	});

	it('should handle namespace transitions with foreignObject', () => {
		function App() {
			return <>
				<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200">
					<rect x="10" y="10" width="50" height="50" fill="red" />
					<foreignObject x="100" y="100" width="80" height="80">
						<div class="html-content">{'HTML inside SVG'}</div>
					</foreignObject>
					<circle cx="50" cy="150" r="20" fill="blue" />
				</svg>
			</>;
		}

		render(App);

		const svg = container.querySelector('svg');
		const rect = container.querySelector('rect');
		const foreignObject = container.querySelector('foreignObject');
		const div = container.querySelector('div');
		const circle = container.querySelector('circle');

		// SVG elements should have SVG namespace
		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(rect.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(foreignObject.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(circle.namespaceURI).toBe('http://www.w3.org/2000/svg');

		// HTML content inside foreignObject should have HTML namespace
		expect(div.namespaceURI).toBe('http://www.w3.org/1999/xhtml');
		expect(div.textContent).toBe('HTML inside SVG');
	});

	it('should render SVG with children as svg elements', () => {
		function SVG({ children }: PropsWithChildren<{}>) {
			return <>
				<svg width={20} height={20} fill="blue" viewBox="0 0 30 10" preserveAspectRatio="none">
					{children}
				</svg>
			</>;
		}

		function App() {
			return <>
				let isDiamond = true;
				<SVG>
					if (isDiamond) {
						<polygon points="0,0 30,0 15,10" />
					} else {
						<polygon points="0,0 30,0 15,10" />
					}
				</SVG>
			</>;
		}

		render(App);

		const svg = container.querySelector('svg');
		const polygon = container.querySelector('polygon');

		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(polygon.namespaceURI).toBe('http://www.w3.org/2000/svg');
	});

	it('should render SVG with props as svg elements', () => {
		function SVG({ Polygon }: PropsWithExtras<{ Polygon: Component }>) {
			return <>
				<svg width={20} height={20} fill="blue" viewBox="0 0 30 10" preserveAspectRatio="none">
					<Polygon />
				</svg>
			</>;
		}

		function App() {
			return <><SVG {Polygon} /></>;
		}

		function Polygon() {
			return <><polygon points="0,0 30,0 15,10" /></>;
		}

		render(App);

		const svg = container.querySelector('svg');
		const polygon = container.querySelector('polygon');

		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(polygon.namespaceURI).toBe('http://www.w3.org/2000/svg');
	});

	it('should render SVG with children as dynamic elements', () => {
		function SVG({ children }: PropsWithChildren<{}>) {
			return <>
				<svg width={20} height={20} fill="blue" viewBox="0 0 30 10" preserveAspectRatio="none">
					{children}
				</svg>
			</>;
		}

		function App() {
			return <>
				let &[dynTag] = track('polygon');
				<SVG>
					<@dynTag points="0,0 30,0 15,10" />
				</SVG>
			</>;
		}

		render(App);

		const svg = container.querySelector('svg');
		const polygon = container.querySelector('polygon');

		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(polygon.namespaceURI).toBe('http://www.w3.org/2000/svg');
	});

	it('should render SVG with children as dynamic components', () => {
		function SVG({ children }: PropsWithChildren<{}>) {
			return <>
				<svg width={20} height={20} fill="blue" viewBox="0 0 30 10" preserveAspectRatio="none">
					{children}
				</svg>
			</>;
		}

		function Polygon({ points }: PropsWithExtras<{ points: string }>) {
			return <><polygon {points} /></>;
		}

		function App() {
			return <>
				let &[Component] = track(() => Polygon);
				<SVG>
					<@Component points="0,0 30,0 15,10" />
				</SVG>
			</>;
		}

		render(App);

		const svg = container.querySelector('svg');
		const polygon = container.querySelector('polygon');

		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(polygon.namespaceURI).toBe('http://www.w3.org/2000/svg');
	});

	it('should render SVG as a dynamic top element with any dynamic children elements', () => {
		function SVG({ children }: PropsWithChildren<{}>) {
			return <>
				let &[tag] = track('svg');
				<@tag width={100} height={50} fill="red" viewBox="0 0 30 10" preserveAspectRatio="none">
					{children}
				</@tag>
			</>;
		}

		function Polygon({ points }: PropsWithExtras<{ points: string }>) {
			return <>
				let &[dynTag] = track('polygon');
				<@dynTag {points} />
			</>;
		}

		function App() {
			return <>
				let &[Component] = track(() => Polygon);
				<SVG>
					<@Component points="0,0 30,0 15,10" />
				</SVG>
			</>;
		}

		render(App);

		const svg = container.querySelector('svg');
		const polygon = container.querySelector('polygon');

		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(polygon.namespaceURI).toBe('http://www.w3.org/2000/svg');
	});

	it('should compare static vs dynamic SVG rendering (original problem case)', () => {
		function App() {
			return <>
				const d = [
					'm14 12 4 4 4-4',
					'M18 16V7',
					'm2 16 4.039-9.69a.5.5 0 0 1 .923 0L11 16',
					'M3.304 13h6.392',
				];
				<div class="container">
					<svg
						xmlns="http://www.w3.org/2000/svg"
						width="24"
						height="24"
						fill="none"
						stroke="currentColor"
						class="dynamic-svg"
					>
						for (const path of d) {
							<path d={path} />
						}
					</svg>

					<svg
						xmlns="http://www.w3.org/2000/svg"
						width="24"
						height="24"
						fill="none"
						stroke="currentColor"
						class="static-svg"
					>
						<path d="m14 12 4 4 4-4" />
						<path d="M18 16V7" />
						<path d="m2 16 4.039-9.69a.5.5 0 0 1 .923 0L11 16" />
						<path d="M3.304 13h6.392" />
					</svg>
				</div>
			</>;
		}

		render(App);

		const dynamicSvg = container.querySelector('.dynamic-svg');
		const staticSvg = container.querySelector('.static-svg');
		const dynamicPaths = dynamicSvg.querySelectorAll('path');
		const staticPaths = staticSvg.querySelectorAll('path');

		// Both SVGs should have correct namespace
		expect(dynamicSvg.namespaceURI).toBe('http://www.w3.org/2000/svg');
		expect(staticSvg.namespaceURI).toBe('http://www.w3.org/2000/svg');

		// Both should have same number of paths
		expect(dynamicPaths.length).toBe(4);
		expect(staticPaths.length).toBe(4);

		// All paths should have SVG namespace
		dynamicPaths.forEach((path) => {
			expect(path.namespaceURI).toBe('http://www.w3.org/2000/svg');
		});
		staticPaths.forEach((path) => {
			expect(path.namespaceURI).toBe('http://www.w3.org/2000/svg');
		});

		// Dynamic and static should have identical path data
		dynamicPaths.forEach((path, i) => {
			expect(path.getAttribute('d')).toBe(staticPaths[i].getAttribute('d'));
		});

		// Critical test: all paths should be proper SVG elements
		dynamicPaths.forEach((path) => {
			expect(path.namespaceURI).toBe('http://www.w3.org/2000/svg');
			expect(path.tagName.toLowerCase()).toBe('path');
		});
		staticPaths.forEach((path) => {
			expect(path.namespaceURI).toBe('http://www.w3.org/2000/svg');
			expect(path.tagName.toLowerCase()).toBe('path');
		});
	});

	it('should render dynamic SVG elements dispatched via a switch inside a for loop', () => {
		function App() {
			return <>
				const iconNodes: [string, Record<string, string>][] = [
					['path', { d: 'm14 12 4 4 4-4' }],
					['circle', { cx: '12', cy: '12', r: '4' }],
					['path', { d: 'M18 16V7' }],
				];
				<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24">
					for (const [tag, attrs] of iconNodes) {
						switch (tag) {
							case 'path':
								<path {...attrs} />
								break;
							case 'circle':
								<circle {...attrs} />
								break;
						}
					}
				</svg>
			</>;
		}

		render(App);

		const svg = container.querySelector('svg');
		expect(svg).toBeTruthy();
		expect(svg.namespaceURI).toBe('http://www.w3.org/2000/svg');

		const paths = svg.querySelectorAll('path');
		const circles = svg.querySelectorAll('circle');

		expect(paths.length).toBe(2);
		expect(circles.length).toBe(1);

		paths.forEach((path) => {
			expect(path.namespaceURI).toBe('http://www.w3.org/2000/svg');
		});
		expect(circles[0].namespaceURI).toBe('http://www.w3.org/2000/svg');

		expect(paths[0].getAttribute('d')).toBe('m14 12 4 4 4-4');
		expect(circles[0].getAttribute('cx')).toBe('12');
		expect(paths[1].getAttribute('d')).toBe('M18 16V7');
	});
});
