import Foundation
import SaplingCore

public protocol GitProvider: Sendable {
    var displayName: String { get }

    func initRepository(at path: URL) async throws -> GitRepository
    func clone(remoteURL: URL, to destinationURL: URL) async throws -> GitRepository
    func repository(at path: URL) -> any Repository
}

public protocol Repository: Sendable {
    var rootURL: URL { get }

    func status() async throws -> [GitFileStatus]
    func add(paths: [String]) async throws
    func commit(message: String) async throws -> GitCommit
    func push(remote: String?, branch: String?) async throws
    func pull(remote: String?, branch: String?) async throws
    func createBranch(named name: String) async throws -> GitBranch
    func switchBranch(named name: String) async throws -> GitBranch
    func merge(branch name: String) async throws
    func addSubmodule(remoteURL: URL, path: String) async throws -> Subproject
    func removeSubmodule(path: String) async throws
    func updateSubmodules(initSubmodules: Bool, recursive: Bool) async throws
    func syncSubmodules(recursive: Bool) async throws
}

public protocol Branch: Sendable {
    var name: String { get }
    var isCurrent: Bool { get }
    var upstreamName: String? { get }
}

public protocol Commit: Sendable {
    var id: String { get }
    var message: String { get }
    var authoredAt: Date { get }
}

public protocol Remote: Sendable {
    var name: String { get }
    var url: URL { get }
}

extension GitBranch: Branch {}
extension GitCommit: Commit {}
extension GitRemote: Remote {}

public enum GitProviderError: Error, Equatable, Sendable {
    case unsupportedOnCurrentPlatform
    case commandFailed(command: String, exitCode: Int32, output: String)
    case invalidRepository(URL)
    case notImplemented(String)
}
