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

describe('SVG namespace handling', () => {
	it('should render static SVG elements with correct namespace', () => {
		component App() {
			<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)', () => {
		component App() {
			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', () => {
		component App() {
			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', () => {
		component App() {
			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', () => {
		component App() {
			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', () => {
		component App() {
			<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', () => {
		component SVG({ children }: PropsWithChildren<{}>) {
			<svg width={20} height={20} fill="blue" viewBox="0 0 30 10" preserveAspectRatio="none">
				{children}
			</svg>
		}

		component App() {
			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', () => {
		component SVG({ Polygon }: PropsWithExtras<{ Polygon: Component }>) {
			<svg width={20} height={20} fill="blue" viewBox="0 0 30 10" preserveAspectRatio="none">
				<Polygon />
			</svg>
		}

		component App() {
			<SVG {Polygon} />
		}

		component Polygon() {
			<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', () => {
		component SVG({ children }: PropsWithChildren<{}>) {
			<svg width={20} height={20} fill="blue" viewBox="0 0 30 10" preserveAspectRatio="none">
				{children}
			</svg>
		}

		component App() {
			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', () => {
		component SVG({ children }: PropsWithChildren<{}>) {
			<svg width={20} height={20} fill="blue" viewBox="0 0 30 10" preserveAspectRatio="none">
				{children}
			</svg>
		}

		component Polygon({ points }: PropsWithExtras<{ points: string }>) {
			<polygon {points} />
		}

		component App() {
			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', () => {
		component SVG({ children }: PropsWithChildren<{}>) {
			let &[tag] = track('svg');
			<@tag width={100} height={50} fill="red" viewBox="0 0 30 10" preserveAspectRatio="none">
				{children}
			</@tag>
		}

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

		component App() {
			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)', () => {
		component App() {
			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', () => {
		component App() {
			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');
	});
});
