import Testing
import Foundation
@testable import Music

struct ConnectionStateTests {

    // Verifies that each valid forward transition is allowed.
    @Test func validTransitionsSucceed() {
        #expect(ConnectionState.disconnected.canTransition(to: .discovering) == true)
        #expect(ConnectionState.discovering.canTransition(to: .foundHost("Mac Mini")) == true)
        #expect(ConnectionState.foundHost("Mac Mini").canTransition(to: .downloadingDB) == true)
        #expect(ConnectionState.downloadingDB.canTransition(to: .connectingCommandChannel) == true)
        #expect(ConnectionState.connectingCommandChannel.canTransition(to: .connected("Mac Mini")) == true)
        #expect(ConnectionState.connected("Mac Mini").canTransition(to: .connectionLost("Network changed")) == true)
        #expect(ConnectionState.connectionLost("Network changed").canTransition(to: .discovering) == true)
    }

    // Verifies that skipping states is rejected.
    @Test func invalidTransitionsRejected() {
        #expect(ConnectionState.disconnected.canTransition(to: .connected("Mac Mini")) == false)
        #expect(ConnectionState.discovering.canTransition(to: .connected("Mac Mini")) == false)
        #expect(ConnectionState.connected("Mac Mini").canTransition(to: .discovering) == false)
    }

    // Any state can transition to disconnected (user can always disconnect).
    @Test func anyStateCanDisconnect() {
        #expect(ConnectionState.discovering.canTransition(to: .disconnected) == true)
        #expect(ConnectionState.foundHost("X").canTransition(to: .disconnected) == true)
        #expect(ConnectionState.downloadingDB.canTransition(to: .disconnected) == true)
        #expect(ConnectionState.connectingCommandChannel.canTransition(to: .disconnected) == true)
        #expect(ConnectionState.connected("X").canTransition(to: .disconnected) == true)
    }

    // Verifies the human-readable status message for each state.
    @Test func userVisibleDescriptions() {
        #expect(ConnectionState.disconnected.userMessage == nil)
        #expect(ConnectionState.discovering.userMessage == "Searching for hosts...")
        #expect(ConnectionState.foundHost("Mac Mini").userMessage == "Found Mac Mini")
        #expect(ConnectionState.downloadingDB.userMessage == "Downloading library...")
        #expect(ConnectionState.connectingCommandChannel.userMessage == "Connecting...")
        #expect(ConnectionState.connected("Mac Mini").userMessage == "Connected to Mac Mini")
        #expect(ConnectionState.connectionLost("Network changed").userMessage == "Connection lost — Network changed")
    }
}
