#!/usr/bin/env node

/**
 * Test Unified Floating System
 *
 * Tests the new unified floating menu system that works consistently
 * for both text and image editing across all document positions
 */

const { TestRunner } = require('./test_runner.js');
const runner = new TestRunner();

runner.describe('Unified Floating System Tests', () => {

    runner.it('should have createFloatingMenu method', async () => {
        // Load editor
        delete require.cache[require.resolve('/home/worsch/markitect_project/markitect/static/editor.js')];
        require('/home/worsch/markitect_project/markitect/static/editor.js');

        if (global.DOMRenderer && global.SectionManager) {
            const container = document.createElement('div');
            container.innerHTML = '<div id="markdown-content"></div>';
            document.body.appendChild(container);

            const manager = new global.SectionManager();
            const renderer = new global.DOMRenderer(manager, container);

            // Verify createFloatingMenu method exists
            runner.expect(typeof renderer.createFloatingMenu).toBe('function');

            // Test basic floating menu creation
            const mockElement = document.createElement('div');
            mockElement.setAttribute('data-section-id', 'test-id');
            Object.defineProperties(mockElement, {
                getBoundingClientRect: {
                    value: () => ({ top: 100, right: 300, bottom: 150, left: 50 })
                }
            });

            renderer.findSectionElement = () => mockElement;

            const testContent = document.createElement('div');
            testContent.textContent = 'Test Content';

            const testControls = document.createElement('div');
            testControls.textContent = 'Test Controls';

            const floatingMenu = renderer.createFloatingMenu('test-id', 'text', testContent, testControls);

            runner.expect(floatingMenu).toBeTruthy();
            runner.expect(floatingMenu.className).toBe('ui-edit-floating-menu');
            runner.expect(floatingMenu.dataset.sectionId).toBe('test-id');
            runner.expect(floatingMenu.dataset.editType).toBe('text');

            // Cleanup
            document.body.removeChild(container);
            if (floatingMenu.parentElement) {
                floatingMenu.remove();
            }
        }
    });

    runner.it('should calculate optimal positioning based on viewport space', async () => {
        if (global.DOMRenderer && global.SectionManager) {
            const container = document.createElement('div');
            container.innerHTML = '<div id="markdown-content"></div>';
            document.body.appendChild(container);

            const manager = new global.SectionManager();
            const renderer = new global.DOMRenderer(manager, container);

            // Test positioning to the right (normal case)
            const mockElement1 = document.createElement('div');
            mockElement1.setAttribute('data-section-id', 'test-right');
            Object.defineProperties(mockElement1, {
                getBoundingClientRect: {
                    value: () => ({ top: 100, right: 200, bottom: 150, left: 50 })
                }
            });

            // Mock wide viewport
            Object.defineProperty(window, 'innerWidth', { value: 1200, configurable: true });

            renderer.findSectionElement = () => mockElement1;

            const testContent = document.createElement('div');
            const testControls = document.createElement('div');
            const floatingMenu1 = renderer.createFloatingMenu('test-right', 'text', testContent, testControls);

            // Should position to the right
            const leftPos1 = parseInt(floatingMenu1.style.left);
            runner.expect(leftPos1).toBeGreaterThan(200); // Right of element

            // Test positioning to the left (narrow viewport)
            const mockElement2 = document.createElement('div');
            mockElement2.setAttribute('data-section-id', 'test-left');
            Object.defineProperties(mockElement2, {
                getBoundingClientRect: {
                    value: () => ({ top: 200, right: 700, bottom: 250, left: 600 })
                }
            });

            // Mock narrow viewport
            Object.defineProperty(window, 'innerWidth', { value: 800, configurable: true });

            renderer.findSectionElement = () => mockElement2;

            const floatingMenu2 = renderer.createFloatingMenu('test-left', 'text', testContent.cloneNode(), testControls.cloneNode());

            // Should position to the left or at minimum distance
            const leftPos2 = parseInt(floatingMenu2.style.left);
            runner.expect(leftPos2).toBeLessThan(600); // Left of element or minimum

            // Cleanup
            document.body.removeChild(container);
            floatingMenu1.remove();
            floatingMenu2.remove();
        }
    });

    runner.it('should create different icons for text vs image editing', async () => {
        if (global.DOMRenderer && global.SectionManager) {
            const container = document.createElement('div');
            container.innerHTML = '<div id="markdown-content"></div>';
            document.body.appendChild(container);

            const manager = new global.SectionManager();
            const renderer = new global.DOMRenderer(manager, container);

            const mockElement = document.createElement('div');
            mockElement.setAttribute('data-section-id', 'test-id');
            Object.defineProperties(mockElement, {
                getBoundingClientRect: {
                    value: () => ({ top: 100, right: 300, bottom: 150, left: 50 })
                }
            });

            renderer.findSectionElement = () => mockElement;

            const testContent = document.createElement('div');
            const testControls = document.createElement('div');

            // Test text editing
            const textMenu = renderer.createFloatingMenu('test-id', 'text', testContent, testControls);
            const textHandle = textMenu.querySelector('.ui-edit-drag-handle');
            runner.expect(textHandle.innerHTML).toContain('📝');
            runner.expect(textHandle.innerHTML).toContain('Editing Text');

            // Test image editing
            const imageMenu = renderer.createFloatingMenu('test-id', 'image', testContent.cloneNode(), testControls.cloneNode());
            const imageHandle = imageMenu.querySelector('.ui-edit-drag-handle');
            runner.expect(imageHandle.innerHTML).toContain('🖼️');
            runner.expect(imageHandle.innerHTML).toContain('Editing Image');

            // Cleanup
            document.body.removeChild(container);
            textMenu.remove();
            imageMenu.remove();
        }
    });

    runner.it('should apply consistent element highlighting', async () => {
        if (global.DOMRenderer && global.SectionManager) {
            const container = document.createElement('div');
            container.innerHTML = '<div id="markdown-content"></div>';
            document.body.appendChild(container);

            const manager = new global.SectionManager();
            const renderer = new global.DOMRenderer(manager, container);

            const mockElement = document.createElement('div');
            mockElement.setAttribute('data-section-id', 'test-id');
            Object.defineProperties(mockElement, {
                getBoundingClientRect: {
                    value: () => ({ top: 100, right: 300, bottom: 150, left: 50 })
                }
            });

            renderer.findSectionElement = () => mockElement;

            const testContent = document.createElement('div');
            const testControls = document.createElement('div');

            // Create floating menu
            const floatingMenu = renderer.createFloatingMenu('test-id', 'text', testContent, testControls);

            // Verify element highlighting
            runner.expect(mockElement.style.outline).toBe('3px solid rgb(0, 123, 255)');
            runner.expect(mockElement.style.outlineOffset).toBe('2px');
            runner.expect(mockElement.style.backgroundColor).toBe('rgba(0, 123, 255, 0.08)');
            runner.expect(mockElement.style.transition).toBe('all 0.2s ease');

            // Cleanup
            document.body.removeChild(container);
            floatingMenu.remove();
        }
    });

    runner.it('should have consistent width and styling', async () => {
        if (global.DOMRenderer && global.SectionManager) {
            const container = document.createElement('div');
            container.innerHTML = '<div id="markdown-content"></div>';
            document.body.appendChild(container);

            const manager = new global.SectionManager();
            const renderer = new global.DOMRenderer(manager, container);

            const mockElement = document.createElement('div');
            mockElement.setAttribute('data-section-id', 'test-id');
            Object.defineProperties(mockElement, {
                getBoundingClientRect: {
                    value: () => ({ top: 100, right: 300, bottom: 150, left: 50 })
                }
            });

            renderer.findSectionElement = () => mockElement;

            const testContent = document.createElement('div');
            const testControls = document.createElement('div');

            const floatingMenu = renderer.createFloatingMenu('test-id', 'text', testContent, testControls);

            // Verify consistent styling
            runner.expect(floatingMenu.style.position).toBe('fixed');
            runner.expect(floatingMenu.style.width).toBe('340px');
            runner.expect(floatingMenu.style.zIndex).toBe('10000');
            runner.expect(floatingMenu.style.borderRadius).toBe('12px');
            runner.expect(floatingMenu.style.display).toBe('flex');
            runner.expect(floatingMenu.style.flexDirection).toBe('column');

            // Verify drag handle exists
            const dragHandle = floatingMenu.querySelector('.ui-edit-drag-handle');
            runner.expect(dragHandle).toBeTruthy();
            runner.expect(dragHandle.style.cursor).toBe('move');

            // Cleanup
            document.body.removeChild(container);
            floatingMenu.remove();
        }
    });

    runner.it('should work with text editor using unified system', async () => {
        if (global.DOMRenderer && global.SectionManager) {
            const container = document.createElement('div');
            container.innerHTML = '<div id="markdown-content"></div>';
            document.body.appendChild(container);

            const manager = new global.SectionManager();
            const renderer = new global.DOMRenderer(manager, container);

            const textMarkdown = '# Test Content';
            const sections = manager.createSectionsFromMarkdown(textMarkdown);
            const textSection = sections[0];

            const mockElement = document.createElement('div');
            mockElement.setAttribute('data-section-id', textSection.id);
            Object.defineProperties(mockElement, {
                getBoundingClientRect: {
                    value: () => ({ top: 100, right: 300, bottom: 150, left: 50 })
                }
            });

            renderer.findSectionElement = () => mockElement;

            // Show text editor
            renderer.showEditor(textSection.id, textSection.currentMarkdown);

            // Verify floating menu was created for text
            const floatingMenu = document.querySelector('.ui-edit-floating-menu');
            runner.expect(floatingMenu).toBeTruthy();
            runner.expect(floatingMenu.dataset.editType).toBe('text');

            // Verify textarea exists
            const textarea = floatingMenu.querySelector('.ui-edit-textarea');
            runner.expect(textarea).toBeTruthy();
            runner.expect(textarea.value).toBe(textSection.currentMarkdown);

            // Cleanup
            document.body.removeChild(container);
            floatingMenu.remove();
        }
    });
});

// Run the tests
if (require.main === module) {
    console.log('🔧 Running Unified Floating System Tests');
    runner.run().then(() => {
        const results = runner.results;
        const failed = results.filter(r => r.status === 'FAIL').length;

        if (failed > 0) {
            console.log(`❌ ${failed} test(s) failed - unified system needs attention`);
            results.forEach(result => {
                if (result.status === 'FAIL') {
                    console.log(`Failed test: ${result.name}`);
                    console.log(`Error: ${result.error}`);
                }
            });
        } else {
            console.log('✅ All unified floating system tests passed!');
        }
    });
}

module.exports = runner;