const { test, expect } = require('@playwright/test');
const { freshEditor, addBlockById, selectComponent, openSettingsTab } = require('./helpers');

test.describe('Video System - Comprehensive', () => {

    test('Check for JS errors on page load', async ({ page }) => {
        const errors = [];
        page.on('pageerror', err => errors.push(err.message));
        page.on('console', msg => {
            if (msg.type() === 'error') errors.push(msg.text());
        });

        await freshEditor(page);
        await page.waitForTimeout(2000);

        console.log('JS Errors:', errors);
        // Filter out expected 404s
        const realErrors = errors.filter(e => !e.includes('404') && !e.includes('Not Found'));
        expect(realErrors).toEqual([]);
    });

    test('Video block: full flow - add, browse, apply, verify in preview', async ({ page }) => {
        await freshEditor(page);
        await page.waitForFunction(() => !!window.assetManager, { timeout: 10000 });

        // 1. Add video block
        const addResult = await addBlockById(page, 'video-block');
        expect(addResult.success).toBe(true);
        await page.waitForTimeout(500);

        // 2. Verify video-wrapper structure
        const structure = await page.evaluate(() => {
            const wrapper = window.editor.getWrapper();
            const videoWrapper = wrapper.find('[data-video-wrapper]')[0];
            if (!videoWrapper) return { error: 'video-wrapper not found' };
            const children = videoWrapper.components().models.map(c => ({
                tag: c.get('tagName'),
                classes: c.getClasses(),
                type: c.get('type'),
            }));
            return { type: videoWrapper.get('type'), children };
        });
        console.log('Video block structure:', JSON.stringify(structure, null, 2));
        expect(structure.type).toBe('video-wrapper');

        // 3. Select and check traits
        await selectComponent(page, '[data-video-wrapper]');
        await page.waitForTimeout(300);
        await openSettingsTab(page);
        await page.waitForTimeout(300);

        const traits = await page.evaluate(() => {
            const sel = window.editor.getSelected();
            return sel.getTraits().map(t => ({ type: t.get('type'), text: t.get('text'), name: t.get('name') }));
        });
        console.log('Video block traits:', JSON.stringify(traits));
        const hasBrowse = traits.some(t => t.text && t.text.includes('Browse Video'));
        expect(hasBrowse).toBe(true);

        // 4. Apply a direct video URL manually
        await page.evaluate(() => {
            const sel = window.editor.getSelected();
            sel.addAttributes({ videoUrl: 'https://www.w3schools.com/html/mov_bbb.mp4' });
            sel.trigger('change:attributes:videoUrl');
        });
        await page.waitForTimeout(500);

        // 5. Check that video-player got the src and placeholder updated
        const afterApply = await page.evaluate(() => {
            const sel = window.editor.getSelected();
            const videoPlayer = sel.components().find(c => c.getClasses().includes('video-player'));
            const placeholder = sel.components().find(c => c.getClasses().includes('video-placeholder'));
            const iframe = sel.components().find(c => c.getClasses().includes('video-frame'));
            return {
                videoPlayer: {
                    src: videoPlayer?.getAttributes()?.src,
                    display: videoPlayer?.getStyle()?.display,
                },
                iframe: {
                    src: iframe?.getAttributes()?.src,
                    display: iframe?.getStyle()?.display,
                },
                placeholder: {
                    display: placeholder?.getStyle()?.display,
                    html: placeholder?.toHTML()?.substring(0, 200),
                },
            };
        });
        console.log('After apply (direct file):', JSON.stringify(afterApply, null, 2));
        expect(afterApply.videoPlayer.src).toBe('https://www.w3schools.com/html/mov_bbb.mp4');
        expect(afterApply.videoPlayer.display).toBe('block');

        // 6. Check the full HTML output includes proper video tag
        const html = await page.evaluate(() => {
            const sel = window.editor.getSelected();
            return sel.toHTML();
        });
        console.log('Video block HTML:', html);
        expect(html).toContain('<video');
        expect(html).toContain('mov_bbb.mp4');
    });

    test('Video block: YouTube URL applies correctly', async ({ page }) => {
        await freshEditor(page);

        await addBlockById(page, 'video-block');
        await page.waitForTimeout(500);
        await selectComponent(page, '[data-video-wrapper]');
        await page.waitForTimeout(300);

        // Apply YouTube URL
        await page.evaluate(() => {
            const sel = window.editor.getSelected();
            sel.addAttributes({ videoUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ' });
            sel.trigger('change:attributes:videoUrl');
        });
        await page.waitForTimeout(500);

        const state = await page.evaluate(() => {
            const sel = window.editor.getSelected();
            const iframe = sel.components().find(c => c.getClasses().includes('video-frame'));
            const video = sel.components().find(c => c.getClasses().includes('video-player'));
            const placeholder = sel.components().find(c => c.getClasses().includes('video-placeholder'));
            return {
                iframe: { src: iframe?.getAttributes()?.src, display: iframe?.getStyle()?.display },
                video: { display: video?.getStyle()?.display },
                placeholder: { display: placeholder?.getStyle()?.display },
            };
        });
        console.log('YouTube apply state:', JSON.stringify(state, null, 2));
        expect(state.iframe.src).toContain('youtube');
        expect(state.iframe.display).toBe('block');
        expect(state.video.display).toBe('none');

        // Check HTML
        const html = await page.evaluate(() => window.editor.getSelected().toHTML());
        console.log('YouTube HTML:', html.substring(0, 300));
        expect(html).toContain('iframe');
        expect(html).toContain('youtube');
    });

    test('Section (Video BG): full flow', async ({ page }) => {
        await freshEditor(page);
        await page.waitForFunction(() => !!window.assetManager, { timeout: 10000 });

        await addBlockById(page, 'section-video-bg');
        await page.waitForTimeout(500);

        // Check structure
        const structure = await page.evaluate(() => {
            const wrapper = window.editor.getWrapper();
            const section = wrapper.find('[data-video-section]')[0];
            if (!section) return { error: 'video-section not found' };
            return {
                type: section.get('type'),
                childTypes: section.components().models.map(c => ({
                    classes: c.getClasses(),
                    type: c.get('type'),
                })),
            };
        });
        console.log('Section Video BG structure:', JSON.stringify(structure, null, 2));
        expect(structure.type).toBe('video-section');

        // Select and verify traits
        await selectComponent(page, '[data-video-section]');
        await page.waitForTimeout(300);
        await openSettingsTab(page);
        await page.waitForTimeout(300);

        const traits = await page.evaluate(() => {
            const sel = window.editor.getSelected();
            return sel.getTraits().map(t => ({ type: t.get('type'), text: t.get('text'), name: t.get('name') }));
        });
        console.log('Section Video BG traits:', JSON.stringify(traits));
        expect(traits.some(t => t.text?.includes('Browse Video'))).toBe(true);

        // Apply video and verify it propagates to bg-video-wrapper
        await page.evaluate(() => {
            const sel = window.editor.getSelected();
            sel.addAttributes({ videoUrl: 'https://www.w3schools.com/html/mov_bbb.mp4' });
            sel.trigger('change:attributes:videoUrl');
        });
        await page.waitForTimeout(500);

        const bgState = await page.evaluate(() => {
            const sel = window.editor.getSelected();
            const bgWrapper = sel.components().find(c => c.getAttributes()['data-bg-video'] === 'true');
            if (!bgWrapper) return { error: 'bg-video-wrapper not found' };
            const bgVideo = bgWrapper.components().find(c => c.getClasses().includes('bg-video-player'));
            const bgIframe = bgWrapper.components().find(c => c.getClasses().includes('bg-video-frame'));
            const bgPlaceholder = bgWrapper.components().find(c => c.getClasses().includes('bg-video-placeholder'));
            return {
                bgVideo: { src: bgVideo?.getAttributes()?.src, display: bgVideo?.getStyle()?.display },
                bgIframe: { display: bgIframe?.getStyle()?.display },
                bgPlaceholder: { display: bgPlaceholder?.getStyle()?.display },
            };
        });
        console.log('Section Video BG after apply:', JSON.stringify(bgState, null, 2));
        expect(bgState.bgVideo.src).toBe('https://www.w3schools.com/html/mov_bbb.mp4');
        expect(bgState.bgVideo.display).toBe('block');

        // Check HTML output
        const html = await page.evaluate(() => window.editor.getSelected().toHTML());
        console.log('Section Video BG HTML:', html.substring(0, 500));
        expect(html).toContain('video');
        expect(html).toContain('mov_bbb.mp4');
    });

    test('Hero (Video): full flow', async ({ page }) => {
        await freshEditor(page);
        await page.waitForFunction(() => !!window.assetManager, { timeout: 10000 });

        await addBlockById(page, 'hero-video');
        await page.waitForTimeout(500);

        // Check it uses video-section type
        const structure = await page.evaluate(() => {
            const wrapper = window.editor.getWrapper();
            const section = wrapper.find('[data-video-section]')[0];
            if (!section) return { error: 'video-section not found' };
            return {
                type: section.get('type'),
                hasOverlay: !!section.components().find(c => c.getClasses().includes('bg-overlay')),
                hasContent: !!section.components().find(c => c.getClasses().includes('bg-content')),
                hasBgVideo: !!section.components().find(c => c.getAttributes()['data-bg-video'] === 'true'),
            };
        });
        console.log('Hero Video structure:', JSON.stringify(structure, null, 2));
        expect(structure.type).toBe('video-section');
        expect(structure.hasBgVideo).toBe(true);
        expect(structure.hasContent).toBe(true);

        // Select and apply video
        await selectComponent(page, '[data-video-section]');
        await page.waitForTimeout(300);
        await openSettingsTab(page);
        await page.waitForTimeout(300);

        // Verify browse button exists
        const browseBtn = page.locator('.panel-right button', { hasText: 'Browse Video Assets' });
        await expect(browseBtn).toBeVisible();

        // Apply video
        await page.evaluate(() => {
            const sel = window.editor.getSelected();
            sel.addAttributes({ videoUrl: 'https://www.w3schools.com/html/mov_bbb.mp4' });
            sel.trigger('change:attributes:videoUrl');
        });
        await page.waitForTimeout(500);

        const html = await page.evaluate(() => window.editor.getSelected().toHTML());
        console.log('Hero Video HTML:', html.substring(0, 500));
        expect(html).toContain('video');
        expect(html).toContain('mov_bbb.mp4');
        expect(html).toContain('Video Background Hero');
    });

    test('Preview renders video correctly', async ({ page, context }) => {
        await freshEditor(page);

        // Add a video block and set URL
        await addBlockById(page, 'video-block');
        await page.waitForTimeout(500);
        await selectComponent(page, '[data-video-wrapper]');
        await page.waitForTimeout(300);

        await page.evaluate(() => {
            const sel = window.editor.getSelected();
            sel.addAttributes({ videoUrl: 'https://www.w3schools.com/html/mov_bbb.mp4' });
            sel.trigger('change:attributes:videoUrl');
        });
        await page.waitForTimeout(500);

        // Check model state: placeholder hidden, video visible
        const modelState = await page.evaluate(() => {
            const sel = window.editor.getSelected();
            const videoPlayer = sel.components().find(c => c.getClasses().includes('video-player'));
            const placeholder = sel.components().find(c => c.getClasses().includes('video-placeholder'));
            return {
                videoDisplay: videoPlayer?.getStyle()?.display,
                videoSrc: videoPlayer?.getAttributes()?.src,
                placeholderDisplay: placeholder?.getStyle()?.display,
            };
        });
        console.log('Model state for export:', JSON.stringify(modelState));
        // Model: video shown, placeholder hidden (correct for preview/export)
        expect(modelState.videoDisplay).toBe('block');
        expect(modelState.videoSrc).toBe('https://www.w3schools.com/html/mov_bbb.mp4');
        expect(modelState.placeholderDisplay).toBe('none');

        // Check HTML output includes proper video tag with src
        const exportedHtml = await page.evaluate(() => {
            const wrapper = window.editor.getWrapper();
            return wrapper.toHTML();
        });
        console.log('Exported HTML snippet:', exportedHtml.substring(0, 500));
        expect(exportedHtml).toContain('<video');
        expect(exportedHtml).toContain('mov_bbb.mp4');

        // Check CSS output: video-player display:block, placeholder display:none
        const exportedCss = await page.evaluate(() => window.editor.getCss());
        console.log('CSS for video-player:', exportedCss.match(/video-player[^}]+}/)?.[0]?.substring(0, 200));
        console.log('CSS for placeholder:', exportedCss.match(/video-placeholder[^}]+}/)?.[0]?.substring(0, 200));
        expect(exportedCss).toContain('display:block');
    });

    test('Browse modal opens and shows server assets', async ({ page }) => {
        await freshEditor(page);
        await page.waitForFunction(() => !!window.assetManager, { timeout: 10000 });

        // Check server has assets
        const serverAssets = await page.evaluate(async () => {
            const resp = await fetch('/api/assets');
            const data = await resp.json();
            return data.assets.filter(a => a.type === 'video');
        });
        console.log('Server video assets:', serverAssets.map(a => a.name));

        // Add video block and open browse
        await addBlockById(page, 'video-block');
        await page.waitForTimeout(500);
        await selectComponent(page, '[data-video-wrapper]');
        await page.waitForTimeout(300);
        await openSettingsTab(page);
        await page.waitForTimeout(300);

        const browseBtn = page.locator('.panel-right button', { hasText: 'Browse Video Assets' });
        await browseBtn.click();
        await page.waitForTimeout(1500);

        const modalState = await page.evaluate(() => {
            const modal = document.getElementById('asset-browser-modal');
            const grid = modal?.querySelector('#asset-browser-grid');
            const items = grid?.querySelectorAll('.asset-browser-item');
            return {
                visible: modal?.classList.contains('visible'),
                activeTab: modal?.querySelector('.asset-tab.active')?.dataset.type,
                itemCount: items?.length || 0,
                items: Array.from(items || []).map(i => i.querySelector('.asset-browser-item-name')?.textContent),
            };
        });
        console.log('Browse modal state:', JSON.stringify(modalState, null, 2));
        expect(modalState.visible).toBe(true);
        expect(modalState.activeTab).toBe('video');

        // If we have items, select one
        if (modalState.itemCount > 0) {
            await page.locator('#asset-browser-grid .asset-browser-item').first().click();
            await page.waitForTimeout(500);

            const appliedUrl = await page.evaluate(() => {
                const sel = window.editor.getSelected();
                return sel?.getAttributes()?.videoUrl;
            });
            console.log('Applied URL from browse:', appliedUrl);
            expect(appliedUrl).toBeTruthy();
        }
    });

    test('No duplicate image/video blocks in Basic section', async ({ page }) => {
        await freshEditor(page);

        const blocks = await page.evaluate(() => {
            return window.editor.BlockManager.getAll().map(b => ({
                id: b.id,
                label: b.get('label'),
                category: typeof b.get('category') === 'string'
                    ? b.get('category')
                    : b.get('category')?.id || b.get('category')?.label || 'unknown',
            }));
        });

        const basicBlocks = blocks.filter(b => b.category === 'Basic');
        const mediaBlocks = blocks.filter(b => b.category === 'Media');

        console.log('Basic blocks:', basicBlocks.map(b => b.id));
        console.log('Media blocks:', mediaBlocks.map(b => b.id));

        // No 'image' or 'video' in Basic (only 'image-block' and 'video-block' in Media)
        expect(basicBlocks.find(b => b.id === 'image')).toBeUndefined();
        expect(basicBlocks.find(b => b.id === 'video')).toBeUndefined();
        expect(mediaBlocks.find(b => b.id === 'image-block')).toBeTruthy();
        expect(mediaBlocks.find(b => b.id === 'video-block')).toBeTruthy();
    });
});
