import Foundation

public enum SaplingDomainError: Error, Equatable, Sendable {
    case workspaceCannotBeInsideProject
    case projectMustBeGitRepository
    case subprojectPathCannotBeEmpty
}

public enum SaplingRules {
    public static func validateWorkspace(_ workspace: Workspace) throws {
        for item in workspace.items {
            try validateWorkspaceItem(item)
        }
    }

    public static func validateProject(_ project: Project) throws {
        guard project.gitRepository.rootURL == project.repositoryURL else {
            throw SaplingDomainError.projectMustBeGitRepository
        }
    }

    public static func validateSubproject(_ subproject: Subproject) throws {
        guard !subproject.path.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty else {
            throw SaplingDomainError.subprojectPathCannotBeEmpty
        }
    }

    private static func validateWorkspaceItem(_ item: WorkspaceItem) throws {
        switch item {
        case .folder(let folder):
            for child in folder.children {
                try validateWorkspaceItem(child)
            }
        case .project(let project):
            try validateProject(project)
        case .subproject(let subproject):
            try validateSubproject(subproject)
        case .file:
            break
        }
    }
}

public enum SaplingSampleData {
    public static let rootURL = URL(fileURLWithPath: "/tmp/SaplingSample")

    public static var document: MarkdownDocument {
        MarkdownDocument(
            url: rootURL.appendingPathComponent("Writing/Editor Prototype.md"),
            title: "Editor Prototype",
            content: """
            # Editor Prototype Notes

            This document exists to test whether Sapling feels comfortable as a writing surface. It should be long enough to scroll, varied enough to exercise Markdown styling, and plain enough that the editor itself stays out of the way.

            The goal for Milestone 1 is not a complete editor. The goal is confidence: text should be easy to enter, easy to revise, and easy to navigate without thinking about the machinery underneath.

            ## What Good Feels Like

            A comfortable editor creates very little friction. The cursor lands where expected. Selection feels native. The page has enough breathing room that long paragraphs are readable, but not so much decoration that the document becomes secondary.

            Useful qualities:

            - The editor owns most of the window.
            - Lines are not stretched across the entire screen.
            - The current line is visible without shouting.
            - Arrow keys, word navigation, and page navigation behave normally.
            - Markdown styling helps scanning but never blocks editing.

            ## Navigation Checklist

            Use this section for quick keyboard testing.

            - [ ] Move with arrow keys.
            - [ ] Jump by word with Option + Arrow.
            - [ ] Extend selection with Shift + Arrow.
            - [ ] Select across multiple lines.
            - [ ] Use Home, End, Page Up, and Page Down.
            - [ ] Type into the active line after moving quickly.

            ## A Normal Paragraph

            Sapling should support the kind of writing that happens in notes, design documents, research logs, and project journals. That means paragraphs should feel calm and readable. The editor should avoid cramped edges, unexpected jumps, and visual noise that pulls attention away from the sentence currently being written.

            Inline Markdown should remain understandable: **strong emphasis** should be easy to spot, *light emphasis* should remain subtle, and links like [Sapling](https://example.com/sapling) should be legible even before full rendering exists.

            ## Code Sample

            ```swift
            struct EditorExperiment {
                var activeLine: Int
                var preservesSelection: Bool

                mutating func move(to line: Int) {
                    activeLine = line
                    preservesSelection = true
                }
            }
            ```

            ## Notes While Testing

            Add observations here while using the prototype for ten or fifteen minutes. The best findings are usually small: a cursor jump, a line that feels too wide, a shortcut that does not behave like a native editor, or a status indicator that creates more distraction than value.

            The prototype is successful when this document feels like something you can keep editing rather than something you are merely testing.
            """
        )
    }

    public static var workspace: Workspace {
        let repositoryURL = rootURL.appendingPathComponent("Research")
        let branch = GitBranch(name: "main", isCurrent: true, upstreamName: "origin/main")
        let remote = GitRemote(
            name: "origin",
            url: URL(string: "https://example.com/sapling/research.git")!
        )
        let repository = GitRepository(
            name: "Research",
            rootURL: repositoryURL,
            currentBranch: branch,
            remotes: [remote],
            statusSummary: .dirty
        )
        let subproject = Subproject(
            name: "Shared Assets",
            path: "Assets/Shared",
            repositoryURL: repositoryURL.appendingPathComponent("Assets/Shared"),
            remoteURL: URL(string: "https://example.com/sapling/shared-assets.git")
        )
        let project = Project(
            name: "Research",
            repositoryURL: repositoryURL,
            gitRepository: repository,
            remotes: [remote],
            branches: [
                branch,
                GitBranch(name: "drafts/editor-prototype")
            ],
            subprojects: [subproject],
            usesGitLFS: true
        )

        return Workspace(
            name: "Sapling Sample",
            rootURL: rootURL,
            items: [
                .folder(
                    WorkspaceFolder(
                        name: "Inbox",
                        url: rootURL.appendingPathComponent("Inbox"),
                        children: [
                            .file(
                                WorkspaceFile(
                                    name: "Scratch.md",
                                    url: rootURL.appendingPathComponent("Inbox/Scratch.md"),
                                    kind: .markdown
                                )
                            )
                        ]
                    )
                ),
                .project(project),
                .subproject(subproject)
            ]
        )
    }
}
