/**
 * JavaScript tests for URL configuration
 * Run with: npm test tests/infrastructure_tests/test_urls.test.js
 */

// Mock the window object for testing
global.window = {};

// Load the URLs configuration
const urlsModule = require('../../src/local_deep_research/web/static/js/config/urls.js');

// Get the exported values from window (for browser environment tests)
const { URLS, URLBuilder } = global.window;

describe('URLs Configuration', () => {
    describe('URL Structure', () => {
        test('URLS object should have required sections', () => {
            expect(URLS).toBeDefined();
            expect(URLS.API).toBeDefined();
            expect(URLS.PAGES).toBeDefined();
            expect(URLS.HISTORY_API).toBeDefined();
            expect(URLS.SETTINGS_API).toBeDefined();
            expect(URLS.METRICS_API).toBeDefined();
        });

        test('Critical API endpoints should be defined', () => {
            const criticalAPIs = [
                'START_RESEARCH',
                'RESEARCH_STATUS',
                'RESEARCH_DETAILS',
                'RESEARCH_LOGS',
                'RESEARCH_REPORT',
                'TERMINATE_RESEARCH',
                'DELETE_RESEARCH',
                'HISTORY'
            ];

            criticalAPIs.forEach(api => {
                expect(URLS.API[api]).toBeDefined();
                expect(typeof URLS.API[api]).toBe('string');
            });
        });

        test('Page routes should be defined', () => {
            const pages = ['HOME', 'PROGRESS', 'RESULTS', 'DETAILS', 'HISTORY', 'SETTINGS', 'METRICS',
                           'NEWS', 'NEWS_SUBSCRIPTIONS', 'BENCHMARK', 'BENCHMARK_RESULTS', 'EMBEDDING_SETTINGS'];

            pages.forEach(page => {
                expect(URLS.PAGES[page]).toBeDefined();
                expect(typeof URLS.PAGES[page]).toBe('string');
            });
        });
    });

    describe('URLBuilder Functionality', () => {
        test('build() should replace {id} placeholders', () => {
            const template = '/api/research/{id}/status';
            const result = URLBuilder.build(template, 123);
            expect(result).toBe('/api/research/123/status');
        });

        test('buildWithReplacements() should handle multiple placeholders', () => {
            const template = '/api/{type}/{id}/action';
            const result = URLBuilder.buildWithReplacements(template, {
                type: 'research',
                id: 456
            });
            expect(result).toBe('/api/research/456/action');
        });

        test('Convenience methods should return correct URLs', () => {
            expect(URLBuilder.progressPage(123)).toBe('/progress/123');
            expect(URLBuilder.resultsPage(456)).toBe('/results/456');
            expect(URLBuilder.detailsPage(789)).toBe('/details/789');
            expect(URLBuilder.researchStatus(111)).toBe('/api/research/111/status');
            expect(URLBuilder.researchDetails(222)).toBe('/api/research/222');
            expect(URLBuilder.researchLogs(333)).toBe('/api/research/333/logs');
            expect(URLBuilder.researchReport(444)).toBe('/api/report/444');
            expect(URLBuilder.terminateResearch(555)).toBe('/api/terminate/555');
            expect(URLBuilder.deleteResearch(666)).toBe('/api/delete/666');
        });

        test('History API convenience methods should work', () => {
            expect(URLBuilder.historyStatus(123)).toBe('/history/status/123');
            expect(URLBuilder.historyDetails(456)).toBe('/history/details/456');
            expect(URLBuilder.historyLogs(789)).toBe('/history/logs/789');
            expect(URLBuilder.historyReport(111)).toBe('/history/report/111');
            expect(URLBuilder.markdownExport(222)).toBe('/api/markdown/222');
        });

        test('Settings API convenience methods should work', () => {
            expect(URLBuilder.getSetting('llm.model')).toBe('/settings/api/llm.model');
            expect(URLBuilder.updateSetting('search.tool')).toBe('/settings/api/search.tool');
            expect(URLBuilder.deleteSetting('custom.key')).toBe('/settings/api/custom.key');
        });

        test('Metrics API convenience methods should work', () => {
            expect(URLBuilder.researchMetrics(123)).toBe('/metrics/api/metrics/research/123');
            expect(URLBuilder.researchTimelineMetrics(456)).toBe('/metrics/api/metrics/research/456/timeline');
            expect(URLBuilder.researchSearchMetrics(789)).toBe('/metrics/api/metrics/research/789/search');
            expect(URLBuilder.getRating(111)).toBe('/metrics/api/ratings/111');
            expect(URLBuilder.saveRating(222)).toBe('/metrics/api/ratings/222');
            expect(URLBuilder.researchCosts(333)).toBe('/metrics/api/research-costs/333');
        });
    });

    describe('URL Pattern Extraction', () => {
        beforeEach(() => {
            // Mock window.location for testing
            delete global.window.location;
            global.window.location = { pathname: '/' };
        });

        test('extractResearchId() should extract ID from various patterns', () => {
            const testCases = [
                { path: '/results/123', expected: '123' },
                { path: '/details/456', expected: '456' },
                { path: '/progress/789', expected: '789' },
                { path: '/home', expected: null },
                { path: '/settings/', expected: null }
            ];

            testCases.forEach(({ path, expected }) => {
                global.window.location.pathname = path;
                expect(URLBuilder.extractResearchId()).toBe(expected);
            });
        });

        test('extractResearchIdFromPattern() should work for specific patterns', () => {
            global.window.location.pathname = '/results/999';
            expect(URLBuilder.extractResearchIdFromPattern('results')).toBe('999');

            global.window.location.pathname = '/details/888';
            expect(URLBuilder.extractResearchIdFromPattern('details')).toBe('888');
            expect(URLBuilder.extractResearchIdFromPattern('results')).toBe(null);
        });

        test('getCurrentPageType() should identify page types', () => {
            const testCases = [
                { path: '/', expected: 'home' },
                { path: '/index', expected: 'home' },
                { path: '/results/123', expected: 'results' },
                { path: '/details/456', expected: 'details' },
                { path: '/progress/789', expected: 'progress' },
                { path: '/history', expected: 'history' },
                { path: '/history/', expected: 'history' },
                { path: '/settings', expected: 'settings' },
                { path: '/settings/advanced', expected: 'settings' },
                { path: '/metrics', expected: 'metrics' },
                { path: '/metrics/costs', expected: 'metrics' },
                { path: '/unknown/path', expected: 'unknown' }
            ];

            testCases.forEach(({ path, expected }) => {
                global.window.location.pathname = path;
                expect(URLBuilder.getCurrentPageType()).toBe(expected);
            });
        });
    });

    describe('URL Consistency Checks', () => {
        test('All URLs should start with /', () => {
            const checkUrls = (obj, path = '') => {
                Object.entries(obj).forEach(([key, value]) => {
                    if (typeof value === 'string') {
                        expect(value).toMatch(/^\//);
                    } else if (typeof value === 'object' && value !== null) {
                        checkUrls(value, `${path}.${key}`);
                    }
                });
            };

            checkUrls(URLS);
        });

        test('URLs with parameters should use consistent placeholder format', () => {
            const checkPlaceholders = (obj) => {
                Object.entries(obj).forEach(([key, value]) => {
                    if (typeof value === 'string') {
                        // Check that placeholders use {name} format
                        const placeholders = value.match(/\{[^}]+\}/g) || [];
                        placeholders.forEach(placeholder => {
                            expect(placeholder).toMatch(/^\{[a-zA-Z_]+\}$/);
                        });
                    } else if (typeof value === 'object' && value !== null) {
                        checkPlaceholders(value);
                    }
                });
            };

            checkPlaceholders(URLS);
        });

        test('API URLs should follow RESTful conventions', () => {
            // URLs ending with ID should be for single resource operations
            const singleResourcePatterns = [
                'RESEARCH_STATUS',
                'RESEARCH_DETAILS',
                'RESEARCH_LOGS',
                'RESEARCH_REPORT',
                'TERMINATE_RESEARCH',
                'DELETE_RESEARCH'
            ];

            singleResourcePatterns.forEach(pattern => {
                expect(URLS.API[pattern]).toMatch(/\{id\}/);
            });

            // Collection URLs should not have ID
            expect(URLS.API.HISTORY).not.toMatch(/\{id\}/);
            expect(URLS.API.CLEAR_HISTORY).not.toMatch(/\{id\}/);
        });

        test('Settings API URLs should be consistent', () => {
            Object.entries(URLS.SETTINGS_API).forEach(([key, url]) => {
                if (key !== 'BASE') {
                    expect(url).toMatch(/^\/settings\//);
                }
            });
        });

        test('Metrics API URLs should be consistent', () => {
            Object.entries(URLS.METRICS_API).forEach(([key, url]) => {
                if (key !== 'BASE') {
                    expect(url).toMatch(/^\/metrics\//);
                }
            });
        });
    });

    describe('Export Validation', () => {
        test('Module should export correctly for different environments', () => {
            // Browser environment (already tested via global.window)
            expect(global.window.URLS).toBeDefined();
            expect(global.window.URLBuilder).toBeDefined();

            // Node.js environment - check the imported module
            expect(urlsModule).toBeDefined();
            expect(urlsModule.URLS).toBeDefined();
            expect(urlsModule.URLBuilder).toBeDefined();
        });
    });
});
