/**
 * SchemaService Unit Tests
 * Verifies hierarchical schema assembly and user-image enrichment using mocked
 * repository responses and a seeded test database fixture.
 */
const SchemaService = require('../../../services/SchemaService');
const TestUtilities = require('../../TestUtilities');

describe('SchemaService', () => {
    let testUtils;
    let traitRepo;
    let service;

    beforeAll(async () => {
        testUtils = new TestUtilities();
        await testUtils.setupTestDatabase();
        await testUtils.insertTestData();

        // Mock trait repository
        traitRepo = {
            getAllCategories: jest.fn(),
            getTraitsByCategory: jest.fn(),
            getOptionsByTrait: jest.fn(),
            getUserImagesByOption: jest.fn()
        };
        service = new SchemaService(traitRepo);
    });

    afterAll(async () => {
        await testUtils.teardownTestDatabase();
    });

    beforeEach(() => {
        jest.clearAllMocks();
    });

    describe('getFullFormSchema', () => {
        it('should throw error if atlasId is not provided', async () => {
            await expect(service.getFullFormSchema()).rejects.toThrow('Atlas ID is required');
        });

        it('should return full form schema for atlas', async () => {
            const mockCategories = [
                {
                    id: 1,
                    nazev_cs: 'Kategorie 1',
                    nazev_en: 'Category 1',
                    poradi: 1
                }
            ];

            const mockTraits = [
                {
                    id: 'test_trait',
                    label_cs: 'Znak 1',
                    label_en: 'Trait 1',
                    popis_cs: 'Popis',
                    popis_en: 'Description'
                }
            ];

            const mockOptions = [
                {
                    id: 1,
                    label_cs: 'Možnost 1',
                    label_en: 'Option 1',
                    images: ['/images/1.jpg'],
                    drawings: ['/drawings/1.jpg']
                }
            ];

            const mockUserImages = [
                { id: 1, image_path: '/user/image1.jpg', is_drawing: false },
                { id: 2, image_path: '/user/drawing1.jpg', is_drawing: true }
            ];

            traitRepo.getAllCategories.mockResolvedValue(mockCategories);
            traitRepo.getTraitsByCategory.mockResolvedValue(mockTraits);
            traitRepo.getOptionsByTrait.mockResolvedValue(mockOptions);
            traitRepo.getUserImagesByOption.mockResolvedValue(mockUserImages);

            const result = await service.getFullFormSchema('test-test-atlas');

            expect(result).toEqual([
                {
                    ...mockCategories[0],
                    znaky: [
                        {
                            ...mockTraits[0],
                            options: [
                                {
                                    ...mockOptions[0],
                                    factoryImages: ['/images/1.jpg'],
                                    factoryDrawings: ['/drawings/1.jpg'],
                                    userImages: [{ id: 1, path: '/user/image1.jpg' }],
                                    userDrawings: [{ id: 2, path: '/user/drawing1.jpg' }]
                                }
                            ]
                        }
                    ]
                }
            ]);

            expect(traitRepo.getAllCategories).toHaveBeenCalledWith('test-test-atlas');
            expect(traitRepo.getTraitsByCategory).toHaveBeenCalledWith(1);
            expect(traitRepo.getOptionsByTrait).toHaveBeenCalledWith('test_trait');
            expect(traitRepo.getUserImagesByOption).toHaveBeenCalledWith(1);
        });

        it('should handle empty user images', async () => {
            const mockCategories = [{ id: 1, nazev_cs: 'Cat', nazev_en: 'Cat', poradi: 1 }];
            const mockTraits = [{ id: 'trait', label_cs: 'Trait', label_en: 'Trait' }];
            const mockOptions = [{ id: 1, label_cs: 'Opt', label_en: 'Opt', images: [], drawings: [] }];

            traitRepo.getAllCategories.mockResolvedValue(mockCategories);
            traitRepo.getTraitsByCategory.mockResolvedValue(mockTraits);
            traitRepo.getOptionsByTrait.mockResolvedValue(mockOptions);
            traitRepo.getUserImagesByOption.mockResolvedValue([]);

            const result = await service.getFullFormSchema('test-test-atlas');

            expect(result[0].znaky[0].options[0]).toEqual({
                id: 1,
                label_cs: 'Opt',
                label_en: 'Opt',
                images: [],
                drawings: [],
                factoryImages: [],
                factoryDrawings: [],
                userImages: [],
                userDrawings: []
            });
        });
    });
});