/**
 * Theme/Dark Mode Tests
 * 
 * Tests for theme switching functionality in app.js
 * Covers localStorage persistence, DOM attribute changes, and icon updates
 */

import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

/**
 * Mock implementation of the theme-related methods from app.js
 * This simulates the actual app behavior for testing
 */
class ThemeManager {
    initTheme() {
        const savedTheme = localStorage.getItem('theme') || 'light';
        this.setTheme(savedTheme);
    }

    setTheme(theme) {
        document.documentElement.setAttribute('data-theme', theme);
        localStorage.setItem('theme', theme);

        const themeIcon = document.querySelector('#theme-toggle i');
        if (themeIcon) {
            themeIcon.className = theme === 'light' ? 'fas fa-moon' : 'fas fa-sun';
        }
    }

    toggleTheme() {
        const currentTheme = document.documentElement.getAttribute('data-theme') || 'light';
        const newTheme = currentTheme === 'light' ? 'dark' : 'light';
        this.setTheme(newTheme);
    }
}

describe('Theme Management', () => {
    let themeManager;

    beforeEach(() => {
        // Reset DOM
        document.body.innerHTML = `
            <button id="theme-toggle">
                <i class="fas fa-moon"></i>
            </button>
        `;
        document.documentElement.removeAttribute('data-theme');
        
        // Clear localStorage
        localStorage.clear();
        
        // Create fresh instance
        themeManager = new ThemeManager();
    });

    afterEach(() => {
        localStorage.clear();
        document.documentElement.removeAttribute('data-theme');
    });

    describe('Theme Initialization', () => {
        it('should initialize with light theme by default when no saved preference', () => {
            themeManager.initTheme();
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('light');
            expect(localStorage.getItem('theme')).toBe('light');
        });

        it('should load saved theme from localStorage', () => {
            localStorage.setItem('theme', 'dark');
            
            themeManager.initTheme();
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
        });

        it('should update theme icon on initialization', () => {
            localStorage.setItem('theme', 'dark');
            
            themeManager.initTheme();
            
            const icon = document.querySelector('#theme-toggle i');
            expect(icon.className).toBe('fas fa-sun');
        });

        it('should handle missing localStorage gracefully', () => {
            // Simulate localStorage not available
            const originalGetItem = Storage.prototype.getItem;
            Storage.prototype.getItem = vi.fn(() => null);
            
            themeManager.initTheme();
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('light');
            
            Storage.prototype.getItem = originalGetItem;
        });
    });

    describe('Theme Setting', () => {
        it('should set light theme correctly', () => {
            themeManager.setTheme('light');
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('light');
            expect(localStorage.getItem('theme')).toBe('light');
        });

        it('should set dark theme correctly', () => {
            themeManager.setTheme('dark');
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
            expect(localStorage.getItem('theme')).toBe('dark');
        });

        it('should update icon to moon for light theme', () => {
            themeManager.setTheme('light');
            
            const icon = document.querySelector('#theme-toggle i');
            expect(icon.className).toBe('fas fa-moon');
        });

        it('should update icon to sun for dark theme', () => {
            themeManager.setTheme('dark');
            
            const icon = document.querySelector('#theme-toggle i');
            expect(icon.className).toBe('fas fa-sun');
        });

        it('should persist theme to localStorage', () => {
            themeManager.setTheme('dark');
            expect(localStorage.getItem('theme')).toBe('dark');
            
            themeManager.setTheme('light');
            expect(localStorage.getItem('theme')).toBe('light');
        });

        it('should handle missing theme icon element gracefully', () => {
            document.body.innerHTML = ''; // Remove theme toggle button
            
            expect(() => {
                themeManager.setTheme('dark');
            }).not.toThrow();
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
        });
    });

    describe('Theme Toggling', () => {
        it('should toggle from light to dark', () => {
            themeManager.setTheme('light');
            
            themeManager.toggleTheme();
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
            expect(localStorage.getItem('theme')).toBe('dark');
        });

        it('should toggle from dark to light', () => {
            themeManager.setTheme('dark');
            
            themeManager.toggleTheme();
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('light');
            expect(localStorage.getItem('theme')).toBe('light');
        });

        it('should update icon when toggling', () => {
            themeManager.setTheme('light');
            let icon = document.querySelector('#theme-toggle i');
            expect(icon.className).toBe('fas fa-moon');
            
            themeManager.toggleTheme();
            icon = document.querySelector('#theme-toggle i');
            expect(icon.className).toBe('fas fa-sun');
        });

        it('should handle multiple toggles correctly', () => {
            themeManager.setTheme('light');
            
            themeManager.toggleTheme(); // light -> dark
            expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
            
            themeManager.toggleTheme(); // dark -> light
            expect(document.documentElement.getAttribute('data-theme')).toBe('light');
            
            themeManager.toggleTheme(); // light -> dark
            expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
        });

        it('should default to light when no theme attribute exists', () => {
            document.documentElement.removeAttribute('data-theme');
            
            themeManager.toggleTheme();
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
        });
    });

    describe('Theme Persistence', () => {
        it('should persist theme across page reloads', () => {
            themeManager.setTheme('dark');
            
            // Simulate page reload by creating new instance
            const newThemeManager = new ThemeManager();
            newThemeManager.initTheme();
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
        });

        it('should maintain theme when toggling multiple times', () => {
            themeManager.initTheme();
            
            themeManager.toggleTheme();
            themeManager.toggleTheme();
            themeManager.toggleTheme();
            
            // Should be dark after 3 toggles (light -> dark -> light -> dark)
            expect(localStorage.getItem('theme')).toBe('dark');
            
            // Reload and verify
            const newThemeManager = new ThemeManager();
            newThemeManager.initTheme();
            expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
        });
    });

    describe('Theme Button Click Handler', () => {
        it('should toggle theme when button is clicked', () => {
            themeManager.initTheme();
            
            const button = document.getElementById('theme-toggle');
            button.addEventListener('click', () => {
                themeManager.toggleTheme();
            });
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('light');
            
            button.click();
            expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
            
            button.click();
            expect(document.documentElement.getAttribute('data-theme')).toBe('light');
        });
    });

    describe('DOM Attribute Application', () => {
        it('should apply data-theme attribute to document root', () => {
            themeManager.setTheme('dark');
            
            const root = document.documentElement;
            expect(root.hasAttribute('data-theme')).toBe(true);
            expect(root.getAttribute('data-theme')).toBe('dark');
        });

        it('should update existing data-theme attribute', () => {
            document.documentElement.setAttribute('data-theme', 'light');
            
            themeManager.setTheme('dark');
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
        });

        it('should work with CSS attribute selectors', () => {
            themeManager.setTheme('dark');
            
            // CSS would use: [data-theme="dark"] { ... }
            const root = document.documentElement;
            const themValue = root.getAttribute('data-theme');
            expect(themValue).toBe('dark');
        });
    });

    describe('Edge Cases', () => {
        it('should handle invalid theme values gracefully', () => {
            themeManager.setTheme('invalid-theme');
            
            // Should still set the attribute and localStorage
            expect(document.documentElement.getAttribute('data-theme')).toBe('invalid-theme');
            expect(localStorage.getItem('theme')).toBe('invalid-theme');
        });

        it('should handle empty string theme', () => {
            themeManager.setTheme('');
            
            expect(document.documentElement.getAttribute('data-theme')).toBe('');
            expect(localStorage.getItem('theme')).toBe('');
        });

        it('should handle rapid theme changes', () => {
            for (let i = 0; i < 10; i++) {
                themeManager.toggleTheme();
            }
            
            // After 10 toggles (even number), should be back to light
            expect(document.documentElement.getAttribute('data-theme')).toBe('light');
        });

        it('should work when localStorage is full', () => {
            // Fill localStorage (though this is hard to truly test)
            const setItemSpy = vi.spyOn(Storage.prototype, 'setItem');
            setItemSpy.mockImplementation(() => {
                throw new Error('QuotaExceededError');
            });
            
            expect(() => {
                themeManager.setTheme('dark');
            }).toThrow();
            
            setItemSpy.mockRestore();
        });
    });
});

describe('Theme Icon Updates', () => {
    let themeManager;

    beforeEach(() => {
        document.body.innerHTML = `
            <button id="theme-toggle">
                <i class="fas fa-moon"></i>
            </button>
        `;
        localStorage.clear();
        themeManager = new ThemeManager();
    });

    it('should use moon icon for light theme', () => {
        themeManager.setTheme('light');
        
        const icon = document.querySelector('#theme-toggle i');
        expect(icon.className).toContain('fa-moon');
        expect(icon.className).not.toContain('fa-sun');
    });

    it('should use sun icon for dark theme', () => {
        themeManager.setTheme('dark');
        
        const icon = document.querySelector('#theme-toggle i');
        expect(icon.className).toContain('fa-sun');
        expect(icon.className).not.toContain('fa-moon');
    });

    it('should update icon class completely (no class accumulation)', () => {
        themeManager.setTheme('light');
        const icon = document.querySelector('#theme-toggle i');
        expect(icon.className).toBe('fas fa-moon');
        
        themeManager.setTheme('dark');
        expect(icon.className).toBe('fas fa-sun');
        expect(icon.className.split(' ').length).toBe(2); // Only 'fas' and 'fa-sun'
    });
});
