import Foundation
import Testing
@testable import Forji

@MainActor
struct MermaidParserTests {

    // MARK: - No mermaid blocks

    @Test func noMermaidBlocks() {
        let markdown = "# Hello\n\nSome regular markdown text."
        let segments = MermaidParser.parse(markdown)
        #expect(segments == [.text(markdown)])
    }

    @Test func emptyString() {
        let segments = MermaidParser.parse("")
        #expect(segments == [.text("")])
    }

    // MARK: - Single mermaid block

    @Test func singleMermaidBlockWithSurroundingText() {
        let markdown = """
        # Title

        Some text before.

        ```mermaid
        graph TD
            A --> B
        ```

        Some text after.
        """
        let segments = MermaidParser.parse(markdown)
        #expect(segments.count == 3)

        if case .text(let before) = segments[0] {
            #expect(before.contains("Title"))
            #expect(before.contains("Some text before."))
        } else {
            Issue.record("Expected .text segment")
        }

        if case .mermaid(let code) = segments[1] {
            #expect(code.contains("graph TD"))
            #expect(code.contains("A --> B"))
        } else {
            Issue.record("Expected .mermaid segment")
        }

        if case .text(let after) = segments[2] {
            #expect(after.contains("Some text after."))
        } else {
            Issue.record("Expected .text segment")
        }
    }

    // MARK: - Multiple mermaid blocks

    @Test func multipleMermaidBlocks() {
        let markdown = """
        Text before first.

        ```mermaid
        graph LR
            A --> B
        ```

        Text between.

        ```mermaid
        sequenceDiagram
            Alice->>Bob: Hello
        ```

        Text after second.
        """
        let segments = MermaidParser.parse(markdown)
        #expect(segments.count == 5)

        if case .text = segments[0] {} else { Issue.record("Expected .text") }
        if case .mermaid(let code1) = segments[1] {
            #expect(code1.contains("graph LR"))
        } else { Issue.record("Expected .mermaid") }
        if case .text = segments[2] {} else { Issue.record("Expected .text") }
        if case .mermaid(let code2) = segments[3] {
            #expect(code2.contains("sequenceDiagram"))
        } else { Issue.record("Expected .mermaid") }
        if case .text = segments[4] {} else { Issue.record("Expected .text") }
    }

    // MARK: - Edge cases

    @Test func mermaidBlockAtStart() {
        let markdown = """
        ```mermaid
        graph TD
            A --> B
        ```

        Text after.
        """
        let segments = MermaidParser.parse(markdown)
        #expect(segments.count == 2)
        if case .mermaid = segments[0] {} else { Issue.record("Expected .mermaid") }
        if case .text = segments[1] {} else { Issue.record("Expected .text") }
    }

    @Test func mermaidBlockAtEnd() {
        let markdown = """
        Text before.

        ```mermaid
        graph TD
            A --> B
        ```
        """
        let segments = MermaidParser.parse(markdown)
        #expect(segments.count == 2)
        if case .text = segments[0] {} else { Issue.record("Expected .text") }
        if case .mermaid = segments[1] {} else { Issue.record("Expected .mermaid") }
    }

    @Test func emptyMermaidBlock() {
        let markdown = """
        Text before.

        ```mermaid
        ```

        Text after.
        """
        let segments = MermaidParser.parse(markdown)
        for segment in segments {
            if case .mermaid = segment {
                Issue.record("Empty mermaid block should be skipped")
            }
        }
    }

    // MARK: - Non-mermaid code blocks

    @Test func nonMermaidCodeBlocksLeftAsText() {
        let markdown = """
        # Code example

        ```python
        print("hello")
        ```

        ```javascript
        console.log("hi")
        ```
        """
        let segments = MermaidParser.parse(markdown)
        #expect(segments == [.text(markdown)])
    }

    @Test func mixedMermaidAndNonMermaidBlocks() {
        let markdown = """
        ```python
        print("hello")
        ```

        ```mermaid
        graph TD
            A --> B
        ```

        ```javascript
        console.log("hi")
        ```
        """
        let segments = MermaidParser.parse(markdown)
        #expect(segments.count == 3)
        if case .text(let before) = segments[0] {
            #expect(before.contains("python"))
        } else { Issue.record("Expected .text") }
        if case .mermaid(let code) = segments[1] {
            #expect(code.contains("graph TD"))
        } else { Issue.record("Expected .mermaid") }
        if case .text(let after) = segments[2] {
            #expect(after.contains("javascript"))
        } else { Issue.record("Expected .text") }
    }
}
