import { describe, it, expect, beforeEach } from 'vitest';
import { Env } from '../models/Env';
import { EnvParam } from '../models/EnvParam';

describe('Environment Management', () => {
    let envs: Env[];

    beforeEach(() => {
        envs = [
            new Env(0, 'DEFAULT', [
                new EnvParam(1, 'host', 'http://localhost'),
                new EnvParam(2, 'port', '8080')
            ]),
            new Env(1, 'env1', [
                new EnvParam(3, 'port', '9090')
            ])
        ];
    });

    describe('add environment', () => {
        it('should create new environment with copied params from current', () => {
            const currentEnv = envs[1]; // env1 with port=9090
            const newEnvName = 'env2';

            // Simulate copying params from current env
            const newEnv = new Env(
                Math.random() * 10000,
                newEnvName,
                [...currentEnv.params]
            );
            envs.push(newEnv);

            expect(envs).toHaveLength(3);
            expect(envs[2].name).toBe('env2');
            expect(envs[2].params).toHaveLength(1);
            expect(envs[2].params[0].name).toBe('port');
            expect(envs[2].params[0].value).toBe('9090');
        });

        it('should create new environment with empty params from DEFAULT', () => {
            const currentEnv = envs[0]; // DEFAULT
            const newEnv = new Env(
                Math.random() * 10000,
                'newEnv',
                [...currentEnv.params]
            );
            envs.push(newEnv);

            expect(envs).toHaveLength(3);
            expect(newEnv.params).toHaveLength(2);
            expect(newEnv.params.map(p => p.name)).toContain('host');
            expect(newEnv.params.map(p => p.name)).toContain('port');
        });
    });

    describe('remove environment', () => {
        it('should not allow removing DEFAULT environment', () => {
            const defaultEnv = envs.find(e => e.name === 'DEFAULT');
            expect(defaultEnv?.isDefault()).toBe(true);
            
            // In the component, this is blocked by check: if (currEnv.isDefault())
            // Simulating the protection
            const canRemove = !defaultEnv?.isDefault();
            expect(canRemove).toBe(false);
        });

        it('should remove non-DEFAULT environment', () => {
            const envToRemove = envs[1]; // env1
            const idx = envs.findIndex(x => x.id === envToRemove.id);
            
            expect(idx).toBe(1);
            expect(envs).toHaveLength(2);

            // Simulate removal
            envs.splice(idx, 1);

            expect(envs).toHaveLength(1);
            expect(envs.find(e => e.id === envToRemove.id)).toBeUndefined();
        });

        it('should select previous environment after removal', () => {
            const idxToRemove = 1; // removing env1
            envs.splice(idxToRemove, 1);

            // After removal, should select max(0, idx-1) = max(0, 0) = 0
            const newSelectedIdx = Math.max(0, idxToRemove - 1);
            expect(newSelectedIdx).toBe(0);
            expect(envs[newSelectedIdx].name).toBe('DEFAULT');
        });
    });

    describe('environment selection', () => {
        it('should find current env by ID from props', () => {
            const selectedId = 1;
            const currEnv = envs.find(e => e.id === selectedId) ?? envs[0];

            expect(currEnv).toBeDefined();
            expect(currEnv.id).toBe(1);
            expect(currEnv.name).toBe('env1');
        });

        it('should fallback to first env if ID not found', () => {
            const selectedId = 999; // non-existent
            const currEnv = envs.find(e => e.id === selectedId) ?? envs[0];

            expect(currEnv).toBeDefined();
            expect(currEnv.id).toBe(0);
            expect(currEnv.name).toBe('DEFAULT');
        });
    });
});
