import ForgejoKit
import SwiftUI

struct CommitDetailView: View {
    let commit: Commit
    let repository: Repository
    @State private var authService: AuthenticationService
    @State private var parsedDiff: ParsedDiff?
    @State private var isLoadingDiff = false
    @State private var errorMessage: String?
    @State private var showError = false

    private let repositoryService: RepositoryService?

    init(commit: Commit, repository: Repository, authService: AuthenticationService) {
        self.commit = commit
        self.repository = repository
        self.authService = authService
        repositoryService = authService.client.map { RepositoryService(client: $0) }
    }

    var body: some View {
        List {
            // Commit info
            Section {
                VStack(alignment: .leading, spacing: 8) {
                    Text(commit.commit.message)
                        .font(.body)

                    HStack(spacing: 8) {
                        if let authorName = commit.author?.login ?? commit.commit.author?.name {
                            Text(authorName)
                                .fontWeight(.medium)
                        }

                        Text(String(commit.sha.prefix(7)))
                            .monospaced()

                        if let date = commit.commit.committer?.date ?? commit.commit.author?.date {
                            Text(formatRelativeDate(date))
                        }
                    }
                    .font(.caption)
                    .foregroundStyle(.secondary)
                }
                .padding(.vertical, 4)
            }

            // Diff
            Section("Changes") {
                if isLoadingDiff {
                    HStack {
                        Spacer()
                        ProgressView()
                        Spacer()
                    }
                    .listRowBackground(Color.clear)
                } else if let parsedDiff {
                    if parsedDiff.files.isEmpty {
                        Text("No file changes")
                            .foregroundStyle(.secondary)
                    } else {
                        DiffView(diff: parsedDiff)
                            .listRowInsets(EdgeInsets())
                    }
                }
            }
        }
        .listStyle(.insetGrouped)
        .navigationTitle(String(commit.sha.prefix(7)))
        .navigationBarTitleDisplayMode(.inline)
        .task {
            await loadDiff()
        }
        .errorAlert(message: $errorMessage, isPresented: $showError)
    }

    private func loadDiff() async {
        guard let repositoryService else { return }
        isLoadingDiff = true
        do {
            let rawDiff = try await repositoryService.fetchCommitDiff(
                owner: repository.owner,
                repo: repository.repoName,
                sha: commit.sha,
            )
            parsedDiff = DiffParser.parse(rawDiff)
        } catch {
            errorMessage = error.localizedDescription
            showError = true
        }
        isLoadingDiff = false
    }
}

#if DEBUG
    #Preview {
        NavigationStack {
            CommitDetailView(
                commit: .preview,
                repository: .preview,
                authService: .previewDefault,
            )
        }
    }
#endif
