import Foundation
import Testing

@testable import Notifying

@Suite("Notifier view model")
struct NotifierTests {

    // MARK: Posting

    @MainActor
    @Suite("Posting")
    struct Posting {

        @Test
        func `posting appends a notification with the given values`() {
            let notifier = Notifier()

            notifier.post(
                .info,
                message: "This is a notification.",
                symbol: "info.circle"
            )

            #expect(notifier.notifications.count == 1)
            #expect(notifier.notifications.first?.kind == .info)
            #expect(notifier.notifications.first?.message == "This is a notification.")
            #expect(notifier.notifications.first?.symbol == "info.circle")
        }

        @Test
        func `posted notifications stack in post order`() {
            let notifier = Notifier()

            notifier.post(
                .info,
                message: "First",
                symbol: "1.circle"
            )
            notifier.post(
                .warning,
                message: "Second",
                symbol: "2.circle"
            )
            notifier.post(
                .error,
                message: "Third",
                symbol: "3.circle"
            )

            #expect(notifier.notifications.map(\.message) == ["First", "Second", "Third"])
        }

    }

    // MARK: Dismissal

    @MainActor
    @Suite("Dismissal")
    struct Dismissal {

        @Test
        func `a notification dismisses itself after the delay`() async throws {
            let notifier = Notifier(
                delayDismissal: .seconds(0.2)
            )

            notifier.post(
                .info,
                message: "This is a notification.",
                symbol: "info.circle"
            )

            try await Task.sleep(for: .seconds(0.1))

            #expect(notifier.notifications.count == 1)

            try await Task.sleep(for: .seconds(0.2))

            #expect(notifier.notifications.isEmpty)
        }

        @Test
        func `notifications dismiss independently`() async throws {
            let notifier = Notifier(
                delayDismissal: .seconds(0.3)
            )

            notifier.post(
                .info,
                message: "First",
                symbol: "1.circle"
            )

            try await Task.sleep(for: .seconds(0.2))

            notifier.post(
                .warning,
                message: "Second",
                symbol: "2.circle"
            )

            try await Task.sleep(for: .seconds(0.2))

            #expect(notifier.notifications.map(\.message) == ["Second"])

            try await Task.sleep(for: .seconds(0.2))

            #expect(notifier.notifications.isEmpty)
        }

    }

}
