import ForgejoKit
import SwiftUI

struct DiffLineHeader: View {
    let path: String
    let line: DiffLine

    var body: some View {
        VStack(spacing: 8) {
            HStack(spacing: 8) {
                Image(systemName: "doc.text")
                    .font(.caption)
                    .foregroundStyle(.secondary)
                Text(path)
                    .font(.system(.caption, design: .monospaced))
                Spacer()
                if let oldLine = line.oldLineNumber {
                    Text("L\(oldLine)")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }
                if let newLine = line.newLineNumber {
                    Text("L\(newLine)")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }
            }

            Text(line.content)
                .font(.system(.caption2, design: .monospaced))
                .foregroundStyle(line.type.color)
                .padding(6)
                .frame(maxWidth: .infinity, alignment: .leading)
                .background(line.type.backgroundColor)
                .clipShape(RoundedRectangle(cornerRadius: 4))
        }
        .padding()
    }
}

struct InlineCommentSheet: View {
    let context: InlineCommentContext
    let prService: PullRequestService
    let owner: String
    let repo: String
    let prNumber: Int
    let isOwnPR: Bool
    var onSubmitted: (() -> Void)?

    @State private var commentBody = ""
    @State private var reviewEvent: ReviewEvent = .comment
    @State private var isSubmitting = false
    @State private var errorMessage: String?
    @State private var showError = false
    @Environment(\.dismiss) private var dismiss

    private var line: DiffLine {
        context.line
    }

    private var path: String {
        context.path
    }

    var body: some View {
        NavigationStack {
            VStack(spacing: 0) {
                DiffLineHeader(path: path, line: line)

                if !isOwnPR {
                    Picker("Type", selection: $reviewEvent) {
                        Label(ReviewEvent.comment.title, systemImage: ReviewEvent.comment.systemImage)
                            .tag(ReviewEvent.comment)
                        Label(ReviewEvent.requestChanges.title, systemImage: ReviewEvent.requestChanges.systemImage)
                            .tag(ReviewEvent.requestChanges)
                    }
                    .pickerStyle(.segmented)
                    .padding(.horizontal)
                }

                TextEditor(text: $commentBody)
                    .frame(maxHeight: .infinity)
                    .scrollContentBackground(.hidden)
                    .padding(8)
                    .background(Color(.tertiarySystemFill))
                    .clipShape(RoundedRectangle(cornerRadius: 8))
                    .padding(.horizontal)
                    .padding(.bottom)
            }
            .navigationTitle("Inline Comment")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Cancel") { dismiss() }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button("Submit") {
                        Task { await submit() }
                    }
                    .disabled(commentBody.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty || isSubmitting)
                }
            }
            .errorAlert(message: $errorMessage, isPresented: $showError)
        }
    }

    private func submit() async {
        guard line.diffPosition != nil else {
            errorMessage = "Cannot comment on this line (no diff position)"
            showError = true
            return
        }
        isSubmitting = true
        do {
            let oldPosition = line.type == .deletion ? line.diffPosition : nil
            let newPosition = line.type == .deletion ? nil : line.diffPosition
            let inlineComment = CreateReviewComment(
                body: commentBody,
                path: path,
                oldPosition: oldPosition,
                newPosition: newPosition,
            )
            _ = try await prService.createReview(
                owner: owner,
                repo: repo,
                index: prNumber,
                body: "",
                event: reviewEvent.rawValue,
                comments: [inlineComment],
            )
            onSubmitted?()
            dismiss()
        } catch {
            errorMessage = error.localizedDescription
            showError = true
        }
        isSubmitting = false
    }
}
