import XCTest
@testable import SaplingEditor

#if os(macOS)
import AppKit

final class MarkdownPresentationSnapshotTests: XCTestCase {
    func testInitialUnfocusedPresentationRendersHeading() {
        let source = "# Heading\nParagraph"
        let snapshot = MarkdownPresentationSnapshot.make(source: source, activeLineIndex: -1)

        XCTAssertTrue(snapshot.signature.contains("system:28.000"))
        XCTAssertTrue(snapshot.signature.contains("hidden=true"))
    }

    func testDirtyActiveLineRoundTripMatchesFreshPresentation() {
        let source = """
        # Heading
        Paragraph with enough words to exercise wrapping and paragraph style.
        * [ ] Move with arrow keys.
        """
        let lineIndex = DocumentLineIndex(source: source)
        let storage = NSTextStorage(string: source)

        MarkdownTextStyler.apply(
            to: storage,
            lineIndex: lineIndex,
            invalidationPlan: EditorDirtyLineInvalidator.plan(
                previousText: nil,
                currentLineIndex: lineIndex,
                edit: nil,
                previousActiveLineIndex: nil,
                currentActiveLineIndex: -1
            ),
            activeLineIndex: -1,
            backgroundColor: .textBackgroundColor,
            activeLineBackgroundColor: .controlAccentColor.withAlphaComponent(0.10),
            textColor: .labelColor,
            secondaryTextColor: .secondaryLabelColor,
            accentColor: .controlAccentColor,
            usesRenderedControls: true
        )

        MarkdownTextStyler.apply(
            to: storage,
            lineIndex: lineIndex,
            invalidationPlan: EditorDirtyLineInvalidationPlan(
                reason: .activeLineChange,
                isFullRender: false,
                dirtyLineIndexes: [1]
            ),
            activeLineIndex: 1,
            backgroundColor: .textBackgroundColor,
            activeLineBackgroundColor: .controlAccentColor.withAlphaComponent(0.10),
            textColor: .labelColor,
            secondaryTextColor: .secondaryLabelColor,
            accentColor: .controlAccentColor,
            usesRenderedControls: true
        )

        MarkdownTextStyler.apply(
            to: storage,
            lineIndex: lineIndex,
            invalidationPlan: EditorDirtyLineInvalidationPlan(
                reason: .activeLineChange,
                isFullRender: false,
                dirtyLineIndexes: [1]
            ),
            activeLineIndex: -1,
            backgroundColor: .textBackgroundColor,
            activeLineBackgroundColor: .controlAccentColor.withAlphaComponent(0.10),
            textColor: .labelColor,
            secondaryTextColor: .secondaryLabelColor,
            accentColor: .controlAccentColor,
            usesRenderedControls: true
        )

        let roundTrip = MarkdownPresentationSnapshot.make(from: storage, lineIndex: lineIndex)
        let fresh = MarkdownPresentationSnapshot.make(source: source, activeLineIndex: -1)

        XCTAssertEqual(roundTrip, fresh)
    }

    func testChecklistContentGeometryIsStableAcrossToggleState() throws {
        let unchecked = "* [ ] Move with arrow keys."
        let checked = "* [x] Move with arrow keys."

        let uncheckedOrigin = MarkdownPresentationSnapshot.contentOrigin(
            source: unchecked,
            text: "Move",
            activeLineIndex: -1,
            usesRenderedControls: true
        )
        let checkedOrigin = MarkdownPresentationSnapshot.contentOrigin(
            source: checked,
            text: "Move",
            activeLineIndex: -1,
            usesRenderedControls: true
        )

        let uncheckedPoint = try XCTUnwrap(uncheckedOrigin)
        let checkedPoint = try XCTUnwrap(checkedOrigin)
        XCTAssertEqual(uncheckedPoint.x, checkedPoint.x, accuracy: 0.001)
        XCTAssertEqual(uncheckedPoint.y, checkedPoint.y, accuracy: 0.001)
    }

    func testParagraphGeometryIsStableAcrossRepeatedPresentation() {
        let source = """
        Intro paragraph with enough words to wrap in a predictable container width for presentation snapshots.

        Another paragraph that should keep the same geometry when presentation is regenerated.
        """

        let first = MarkdownPresentationSnapshot.make(source: source, activeLineIndex: -1, containerWidth: 240)
        let second = MarkdownPresentationSnapshot.make(source: source, activeLineIndex: -1, containerWidth: 240)

        XCTAssertEqual(first, second)
    }
}
#endif
