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

// Mock dell'I/O su disco: i test non toccano il filesystem reale né dipendono
// dal path relativo a src/.
vi.mock('fs', () => ({
    readFileSync: vi.fn(),
    writeFileSync: vi.fn(),
    mkdirSync: vi.fn(),
    existsSync: vi.fn(),
}))

import * as fs from 'fs'
import { loadState, saveState } from '../../src/persist.js'
import { createInitialState } from '../../src/gameState.js'

describe('Persistenza stato (persist.js)', () => {
    beforeEach(() => {
        vi.clearAllMocks()
    })

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

    describe('saveState', () => {
        it('crea la directory e scrive lo stato serializzato', () => {
            const state = createInitialState()
            saveState(state)

            expect(fs.mkdirSync).toHaveBeenCalledWith(expect.any(String), { recursive: true })
            expect(fs.writeFileSync).toHaveBeenCalled()

            const [, contenuto, encoding] = fs.writeFileSync.mock.calls[0]
            expect(JSON.parse(contenuto)).toEqual(state)
            expect(encoding).toBe('utf8')
        })

        it('non lancia eccezioni se la scrittura fallisce', () => {
            fs.mkdirSync.mockImplementation(() => { throw new Error('EACCES') })
            const errSpy = vi.spyOn(console, 'error').mockImplementation(() => {})

            expect(() => saveState(createInitialState())).not.toThrow()
            expect(errSpy).toHaveBeenCalled()
        })
    })

    describe('loadState', () => {
        it('legge e fa il parse di un file valido', () => {
            const salvato = createInitialState()
            salvato.sp.nomi.home = 'Squadra X'
            fs.existsSync.mockReturnValue(true)
            fs.readFileSync.mockReturnValue(JSON.stringify(salvato))

            expect(loadState()).toEqual(salvato)
        })

        it('ritorna lo stato iniziale se il file non esiste', () => {
            fs.existsSync.mockReturnValue(false)
            expect(loadState()).toEqual(createInitialState())
        })

        it('ritorna lo stato iniziale se il JSON è corrotto', () => {
            fs.existsSync.mockReturnValue(true)
            fs.readFileSync.mockReturnValue('{ questo non è json')
            const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {})

            expect(loadState()).toEqual(createInitialState())
            expect(warnSpy).toHaveBeenCalled()
        })
    })
})
