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("Research/README.md"),
            title: "README",
            content: """
            # Sapling

            Sapling is a **Git-native** Markdown workspace.

            - [x] Model local workspaces
            - [ ] Render inactive Markdown lines

            ```swift
            let workspace = Workspace(name: "Research", rootURL: url)
            ```

            ![Architecture](attachments/architecture.png)
            """
        )
    }

    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)
            ]
        )
    }
}
