import { describe, it, expect, vi, afterEach } from 'vitest'
import { getNetworkIPs, collectIPs, printServerInfo } from '../../src/server-utils.js'

// Nota: gli IP vengono iniettati nei test (oggetto stile os.networkInterfaces o
// array di IP), così i risultati sono deterministici su qualsiasi piattaforma —
// incluso WSL, dove getNetworkIPs() userebbe altrimenti PowerShell.

describe('Server Utils', () => {

    afterEach(() => {
        vi.restoreAllMocks()
    })

    // =============================================
    // getNetworkIPs / collectIPs
    // =============================================
    describe('getNetworkIPs', () => {
        it('dovrebbe restituire indirizzi IPv4 non-loopback', () => {
            expect(getNetworkIPs({
                eth0: [{ family: 'IPv4', internal: false, address: '192.168.1.100' }]
            })).toEqual(['192.168.1.100'])
        })

        it('dovrebbe escludere indirizzi loopback (internal)', () => {
            const ips = getNetworkIPs({
                lo: [{ family: 'IPv4', internal: true, address: '127.0.0.1' }],
                eth0: [{ family: 'IPv4', internal: false, address: '192.168.1.100' }]
            })
            expect(ips).not.toContain('127.0.0.1')
            expect(ips).toContain('192.168.1.100')
        })

        it('dovrebbe escludere indirizzi IPv6', () => {
            const ips = getNetworkIPs({
                eth0: [
                    { family: 'IPv6', internal: false, address: 'fe80::1' },
                    { family: 'IPv4', internal: false, address: '192.168.1.100' }
                ]
            })
            expect(ips).toEqual(['192.168.1.100'])
        })

        it('dovrebbe escludere bridge Docker 172.17.x.x', () => {
            const ips = getNetworkIPs({
                docker0: [{ family: 'IPv4', internal: false, address: '172.17.0.1' }],
                eth0: [{ family: 'IPv4', internal: false, address: '10.0.0.5' }]
            })
            expect(ips).not.toContain('172.17.0.1')
            expect(ips).toContain('10.0.0.5')
        })

        it('dovrebbe escludere bridge Docker 172.18.x.x', () => {
            expect(getNetworkIPs({
                br0: [{ family: 'IPv4', internal: false, address: '172.18.0.1' }]
            })).toEqual([])
        })

        it('dovrebbe escludere indirizzi link-local 169.254.x.x', () => {
            expect(getNetworkIPs({
                eth0: [{ family: 'IPv4', internal: false, address: '169.254.1.1' }]
            })).toEqual([])
        })

        it('dovrebbe restituire array vuoto se nessuna interfaccia disponibile', () => {
            expect(getNetworkIPs({})).toEqual([])
        })

        it('dovrebbe restituire più indirizzi da interfacce diverse', () => {
            const ips = getNetworkIPs({
                eth0: [{ family: 'IPv4', internal: false, address: '192.168.1.100' }],
                wlan0: [{ family: 'IPv4', internal: false, address: '192.168.1.101' }]
            })
            expect(ips).toHaveLength(2)
            expect(ips).toContain('192.168.1.100')
            expect(ips).toContain('192.168.1.101')
        })

        it('collectIPs gestisce input vuoto/undefined senza errori', () => {
            expect(collectIPs()).toEqual([])
            expect(collectIPs({})).toEqual([])
        })
    })

    // =============================================
    // printServerInfo
    // =============================================
    describe('printServerInfo', () => {
        it('dovrebbe stampare la porta di default (3000)', () => {
            const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
            printServerInfo(3000, [])
            const allLogs = consoleSpy.mock.calls.map(c => c[0]).join('\n')
            expect(allLogs).toContain('3000')
            expect(allLogs).toContain('/display')
            expect(allLogs).toContain('/controller')
            consoleSpy.mockRestore()
        })

        it('dovrebbe stampare la porta personalizzata', () => {
            const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
            printServerInfo(8080, [])
            const allLogs = consoleSpy.mock.calls.map(c => c[0]).join('\n')
            expect(allLogs).toContain('8080')
            consoleSpy.mockRestore()
        })

        it('dovrebbe mostrare gli URL remoti se ci sono IP di rete', () => {
            const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
            printServerInfo(3000, ['192.168.1.50'])
            const allLogs = consoleSpy.mock.calls.map(c => c[0]).join('\n')
            expect(allLogs).toContain('192.168.1.50')
            expect(allLogs).toContain('remoti')
            consoleSpy.mockRestore()
        })

        it('non dovrebbe mostrare sezione remoti se nessun IP di rete', () => {
            const consoleSpy = vi.spyOn(console, 'log').mockImplementation(() => {})
            printServerInfo(3000, [])
            const allLogs = consoleSpy.mock.calls.map(c => c[0]).join('\n')
            expect(allLogs).not.toContain('remoti')
            consoleSpy.mockRestore()
        })
    })
})
