//  🖥️ TUIKit — Terminal UI Kit for Swift
//  AlertPresentationModifierTests.swift
//
//  Created by LAYERED.work
//  License: MIT  dimming, centering, and alert rendering.
//

import Testing

@testable import TUIkit

@MainActor
@Suite("AlertPresentationModifier Tests")
struct AlertPresentationModifierTests {

    /// Helper to create a RenderContext with default test settings.
    private func testContext() -> RenderContext {
        RenderContext(
            availableWidth: 80,
            availableHeight: 24,
            tuiContext: TUIContext()
        )
    }

    /// Helper to render a view to a FrameBuffer.
    private func render<V: View>(_ view: V) -> FrameBuffer {
        renderToBuffer(view, context: testContext())
    }

    @Test("Alert not presented shows only base content")
    func notPresentedShowsBase() {
        let isPresented = Binding.constant(false)
        let view = Text("Base Content")
            .alert("Title", isPresented: isPresented, actions: { EmptyView() }, message: { Text("Message") })

        let buffer = render(view)
        let content = buffer.lines.joined(separator: "\n").stripped

        #expect(content.contains("Base Content"))
        #expect(!content.contains("Title"))
        #expect(!content.contains("Message"))
    }

    @Test("Alert presented shows dimmed base with alert overlay")
    func presentedShowsAlert() {
        let isPresented = Binding.constant(true)
        let view = VStack {
            Text("Base Content")
            Text("More base text")
        }
        .alert("Alert Title", isPresented: isPresented, actions: { EmptyView() }, message: { Text("Alert Message") })

        let buffer = render(view)

        // Alert content should be present
        let stripped = buffer.lines.joined(separator: "\n").stripped
        #expect(stripped.contains("Alert Title"))
        #expect(stripped.contains("Alert Message"))

        // At least some content should have dim codes (from dimmed base)
        // The dimmed modifier wraps content, so check for dim in raw output
        let rawContent = buffer.lines.joined(separator: "\n")
        #expect(rawContent.contains("\u{1B}["))  // Contains ANSI codes
    }

    @Test("Alert with actions renders action buttons")
    func alertWithActions() {
        let isPresented = Binding.constant(true)
        let view = Text("Base")
            .alert("Warning", isPresented: isPresented, actions: {
                Button("Yes") { }
                Button("No") { }
            }, message: { Text("Are you sure?") })

        let buffer = render(view)
        let content = buffer.lines.joined(separator: "\n").stripped

        #expect(content.contains("Warning"))
        #expect(content.contains("Are you sure?"))
        #expect(content.contains("Yes"))
        #expect(content.contains("No"))
    }

    @Test("Alert without message renders title and actions only")
    func alertWithoutMessage() {
        let isPresented = Binding.constant(true)
        let view = Text("Base")
            .alert("Just Title", isPresented: isPresented, actions: {
                Button("OK") { }
            })

        let buffer = render(view)
        let content = buffer.lines.joined(separator: "\n").stripped

        #expect(content.contains("Just Title"))
        #expect(content.contains("OK"))
    }

    @Test("Alert respects custom colors")
    func customColors() {
        let isPresented = Binding.constant(true)
        let view = Text("Base")
            .alert(
                "Custom",
                isPresented: isPresented,
                actions: { EmptyView() },
                message: { Text("Message") },
                borderColor: .red,
                titleColor: .yellow
            )

        let buffer = render(view)
        let content = buffer.lines.joined(separator: "\n")

        // Should contain ANSI color codes (non-empty buffer with styling)
        #expect(!buffer.isEmpty)
        #expect(content.contains("\u{1B}["))
    }

    @Test("Toggle isPresented switches between states")
    func togglePresentation() {
        @State var showAlert = false

        let view1 = Text("Content")
            .alert("Alert", isPresented: $showAlert, actions: { EmptyView() }, message: { Text("Test") })

        let buffer1 = render(view1)
        let content1 = buffer1.lines.joined(separator: "\n").stripped

        // Initially not shown
        #expect(!content1.contains("Alert"))

        // Toggle to show
        showAlert = true
        let view2 = Text("Content")
            .alert("Alert", isPresented: $showAlert, actions: { EmptyView() }, message: { Text("Test") })

        let buffer2 = render(view2)
        let content2 = buffer2.lines.joined(separator: "\n").stripped

        // Now shown
        #expect(content2.contains("Alert"))
    }
}
