import SwiftUI
import PhotosUI
import ComposeApp

/// Wrapper to retain the Kotlin ViewModel via @StateObject
private class CompletionViewModelHolder: ObservableObject {
    let vm = ComposeApp.TaskCompletionViewModel()
}

struct CompleteTaskView: View {
    let task: TaskResponse
    let onComplete: (TaskResponse?) -> Void  // Pass back updated task

    @Environment(\.dismiss) private var dismiss
    @StateObject private var taskViewModel = TaskViewModel()
    @StateObject private var contractorViewModel = ContractorViewModel()
    @StateObject private var completionHolder = CompletionViewModelHolder()
    private var completionViewModel: ComposeApp.TaskCompletionViewModel { completionHolder.vm }
    @State private var completedByName: String = ""
    @State private var actualCost: String = ""
    @State private var notes: String = ""
    @State private var rating: Int = 3
    @State private var selectedItems: [PhotosPickerItem] = []
    @State private var selectedImages: [UIImage] = []
    @State private var isSubmitting: Bool = false
    @State private var showError: Bool = false
    @State private var errorMessage: String = ""
    @State private var showCamera: Bool = false
    @State private var selectedContractor: ContractorSummary? = nil
    @State private var showContractorPicker: Bool = false
    @State private var observationTask: Task<Void, Never>? = nil

    var body: some View {
        NavigationStack {
            Form {
                // Task Info Section
                Section {
                    VStack(alignment: .leading, spacing: 8) {
                        Text(task.title)
                            .font(.headline)

                        HStack {
                            Label((task.categoryName ?? "").capitalized, systemImage: "folder")
                                .font(.subheadline)
                                .foregroundStyle(.secondary)

                            Spacer()

                            if task.inProgress {
                                Text(L10n.Tasks.inProgress)
                                    .font(.caption)
                                    .foregroundStyle(.secondary)
                                    .padding(.horizontal, 8)
                                    .padding(.vertical, 4)
                                    .background(.quaternary)
                                    .clipShape(Capsule())
                            }
                        }
                    }
                } header: {
                    Text(L10n.Tasks.taskDetails)
                }
                .sectionBackground()

                // Contractor Selection Section
                Section {
                    Button(action: {
                        showContractorPicker = true
                    }) {
                        HStack {
                            Label(L10n.Tasks.selectContractor, systemImage: "wrench.and.screwdriver")
                                .foregroundStyle(.primary)

                            Spacer()

                            if let contractor = selectedContractor {
                                VStack(alignment: .trailing) {
                                    Text(contractor.name)
                                        .foregroundStyle(.secondary)
                                    if let company = contractor.company {
                                        Text(company)
                                            .font(.caption)
                                            .foregroundStyle(.tertiary)
                                    }
                                }
                            } else {
                                Text(L10n.Tasks.none)
                                    .foregroundStyle(.tertiary)
                            }

                            Image(systemName: "chevron.right")
                                .font(.caption)
                                .foregroundStyle(.tertiary)
                        }
                    }
                    .accessibilityIdentifier("TaskCompletion.ContractorPicker")
                } header: {
                    Text(L10n.Tasks.contractorOptional)
                } footer: {
                    Text(L10n.Tasks.contractorHelper)
                }
                .sectionBackground()

                // Completion Details Section
                Section {
                    LabeledContent {
                        TextField(L10n.Tasks.yourName, text: $completedByName)
                            .multilineTextAlignment(.trailing)
                            .disabled(selectedContractor != nil)
                    } label: {
                        Label(L10n.Tasks.completedBy, systemImage: "person")
                    }

                    LabeledContent {
                        TextField("0.00", text: $actualCost)
                            .keyboardType(.decimalPad)
                            .multilineTextAlignment(.trailing)
                            .overlay(alignment: .leading) {
                                Text("$")
                                    .foregroundStyle(.secondary)
                            }
                            .padding(.leading, 12)
                            .keyboardDismissToolbar()
                            .accessibilityIdentifier(AccessibilityIdentifiers.Task.actualCostField)
                    } label: {
                        Label(L10n.Tasks.actualCost, systemImage: "dollarsign.circle")
                    }
                } header: {
                    Text(L10n.Tasks.optionalInfo)
                } footer: {
                    Text(L10n.Tasks.optionalDetails)
                }
                .sectionBackground()

                // Notes Section
                Section {
                    VStack(alignment: .leading, spacing: 8) {
                        Label(L10n.Tasks.notes, systemImage: "note.text")
                            .font(.subheadline)
                            .foregroundStyle(.secondary)

                        TextEditor(text: $notes)
                            .frame(minHeight: 100)
                            .scrollContentBackground(.hidden)
                            .keyboardDismissToolbar()
                            .accessibilityIdentifier(AccessibilityIdentifiers.Task.notesField)
                    }
                } footer: {
                    Text(L10n.Tasks.optionalNotes)
                }
                .sectionBackground()

                // Rating Section
                Section {
                    VStack(spacing: 12) {
                        HStack {
                            Label(L10n.Tasks.qualityRating, systemImage: "star")
                                .font(.subheadline)

                            Spacer()

                            Text("\(rating) / 5")
                                .font(.subheadline)
                                .foregroundStyle(.secondary)
                        }

                        HStack(spacing: 16) {
                            ForEach(1...5, id: \.self) { star in
                                Image(systemName: star <= rating ? "star.fill" : "star")
                                    .font(.title2)
                                    .foregroundStyle(star <= rating ? .yellow : .gray)
                                    .symbolRenderingMode(.hierarchical)
                                    .onTapGesture {
                                        withAnimation(.easeInOut(duration: 0.2)) {
                                            rating = star
                                        }
                                    }
                            }
                        }
                        .frame(maxWidth: .infinity)
                    }
                    .accessibilityIdentifier(AccessibilityIdentifiers.Task.ratingView)
                    .accessibilityElement(children: .combine)
                    .accessibilityLabel("Rating: \(rating) out of 5 stars")
                    .accessibilityAdjustableAction { direction in
                        switch direction {
                        case .increment:
                            if rating < 5 { rating += 1 }
                        case .decrement:
                            if rating > 1 { rating -= 1 }
                        @unknown default:
                            break
                        }
                    }
                } footer: {
                    Text(L10n.Tasks.rateQuality)
                }
                .sectionBackground()

                // Images Section
                Section {
                    VStack(alignment: .leading, spacing: 12) {
                        HStack(spacing: 12) {
                            Button(action: {
                                showCamera = true
                            }) {
                                Label(L10n.Tasks.takePhoto, systemImage: "camera")
                                    .frame(maxWidth: .infinity)
                                    .foregroundStyle(Color.appPrimary)
                            }
                            .buttonStyle(.bordered)

                            PhotosPicker(
                                selection: $selectedItems,
                                maxSelectionCount: 5,
                                matching: .images,
                                photoLibrary: .shared()
                            ) {
                                Label(L10n.Tasks.library, systemImage: "photo.on.rectangle.angled")
                                    .frame(maxWidth: .infinity)
                                    .foregroundStyle(Color.appPrimary)
                            }
                            .buttonStyle(.bordered)
                        }
                        .onChange(of: selectedItems) { _, newItems in
                            Task {
                                selectedImages = []
                                for item in newItems {
                                    if let data = try? await item.loadTransferable(type: Data.self),
                                       let image = UIImage(data: data) {
                                        selectedImages.append(image)
                                    }
                                }
                            }
                        }

                        // Display selected images
                        if !selectedImages.isEmpty {
                            ScrollView(.horizontal, showsIndicators: false) {
                                HStack(spacing: 12) {
                                    ForEach(selectedImages.indices, id: \.self) { index in
                                        ImageThumbnailView(
                                            image: selectedImages[index],
                                            onRemove: {
                                                withAnimation {
                                                    selectedImages.remove(at: index)
                                                    // Camera photos don't exist in selectedItems.
                                                    // Guard the index to avoid out-of-bounds crashes.
                                                    if index < selectedItems.count {
                                                        selectedItems.remove(at: index)
                                                    }
                                                }
                                            }
                                        )
                                    }
                                }
                                .padding(.vertical, 4)
                            }
                        }
                    }
                } header: {
                    Text("\(L10n.Tasks.photos) (\(selectedImages.count)/5)")
                } footer: {
                    Text(L10n.Tasks.addPhotos)
                }
                .sectionBackground()

                // Complete Button Section
                Section {
                    Button(action: handleComplete) {
                        HStack {
                            if isSubmitting {
                                ProgressView()
                                    .tint(.white)
                            } else {
                                Label(L10n.Tasks.completeTask, systemImage: "checkmark.circle.fill")
                            }
                        }
                        .frame(maxWidth: .infinity)
                        .fontWeight(.semibold)
                    }
                    .accessibilityIdentifier(AccessibilityIdentifiers.Task.submitButton)
                    .listRowBackground(isSubmitting ? Color.gray : Color.appPrimary)
                    .foregroundStyle(Color.appTextOnPrimary)
                    .disabled(isSubmitting)
                }
            }
            .standardFormStyle()
            .background(WarmGradientBackground())
            .navigationTitle(L10n.Tasks.completeTask)
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button(L10n.Common.cancel) {
                        dismiss()
                    }
                }
            }
            .alert(L10n.Tasks.error, isPresented: $showError) {
                Button(L10n.Common.ok, role: .cancel) {}
            } message: {
                Text(errorMessage)
            }
            .sheet(isPresented: $showCamera) {
                CameraPickerView { image in
                    if selectedImages.count < 5 {
                        selectedImages.append(image)
                    }
                }
            }
            .sheet(isPresented: $showContractorPicker) {
                ContractorPickerView(
                    selectedContractor: $selectedContractor,
                    contractorViewModel: contractorViewModel
                )
            }
            .onAppear {
                contractorViewModel.loadContractors()
            }
            .onDisappear {
                observationTask?.cancel()
                observationTask = nil
            }
            .handleErrors(
                error: errorMessage,
                onRetry: { handleComplete() }
            )
        }
    }

    private func handleComplete() {
        guard TokenStorage.shared.getToken() != nil else {
            errorMessage = "Not authenticated"
            showError = true
            return
        }

        isSubmitting = true

        // New direct-to-B2 upload path: downsample on-device, presign, POST
        // straight to B2, pass the resulting upload_ids to the completion
        // create call. Bytes never traverse our API server. See
        // /api/uploads/presign in honeyDueAPI-go.
        if !selectedImages.isEmpty {
            uploadAndCreate()
        } else {
            // No images — go straight to the completion create.
            let request = TaskCompletionCreateRequest(
                taskId: task.id,
                completedAt: nil,
                notes: notes.isEmpty ? nil : notes,
                actualCost: actualCost.isEmpty ? nil : KotlinDouble(double: Double(actualCost) ?? 0.0),
                rating: KotlinInt(int: Int32(rating)),
                uploadIds: nil
            )
            completionViewModel.createTaskCompletion(request: request)
            observeCompletionState()
        }
    }

    /// Async pipeline: downsample → presign+upload to B2 → create completion
    /// with the returned upload_ids. Errors at any stage become a single
    /// alert; partial uploads (1 of 3 succeeded) currently fail the whole
    /// flow — server-side cleanup reaps the orphans within the hour.
    private func uploadAndCreate() {
        observationTask?.cancel()
        observationTask = Task {
            // Step 1: downsample each image. Runs on the calling task; the
            // ImageDownsampler is memory-bounded so this is safe for the
            // expected batch sizes (≤5 images).
            let payloads: [(Data, String)] = selectedImages.compactMap { uiImage -> (Data, String)? in
                guard let data = ImageDownsampler.downsample(uiImage: uiImage, profile: .completion) else {
                    return nil
                }
                return (data, "completion_\(UUID().uuidString).jpg")
            }
            guard payloads.count == selectedImages.count else {
                await MainActor.run {
                    errorMessage = "One or more photos couldn't be processed."
                    showError = true
                    isSubmitting = false
                }
                return
            }

            // Step 2: presign + upload each to B2. PresignedUploader runs
            // them in parallel under a server-enforced concurrency cap of 10.
            guard let uploader = PresignedUploader() else {
                await MainActor.run {
                    errorMessage = "Not authenticated"
                    showError = true
                    isSubmitting = false
                }
                return
            }
            let uploadIds: [Int32]
            do {
                uploadIds = try await uploader.uploadAll(items: payloads, category: .completion)
            } catch {
                await MainActor.run {
                    errorMessage = (error as? PresignedUploaderError)?.errorDescription
                        ?? error.localizedDescription
                    showError = true
                    isSubmitting = false
                }
                return
            }

            // Step 3: create completion via the existing endpoint, passing
            // upload_ids so the server claims the pending_uploads rows and
            // turns them into TaskCompletionImage rows.
            let request = TaskCompletionCreateRequest(
                taskId: task.id,
                completedAt: nil,
                notes: notes.isEmpty ? nil : notes,
                actualCost: actualCost.isEmpty ? nil : KotlinDouble(double: Double(actualCost) ?? 0.0),
                rating: KotlinInt(int: Int32(rating)),
                uploadIds: uploadIds.map { KotlinInt(int: $0) }
            )
            await MainActor.run {
                completionViewModel.createTaskCompletion(request: request)
            }
            await observeCompletionStateAsync()
        }
    }

    /// Observe the createCompletionState StateFlow until a terminal value
    /// arrives, then dismiss or surface an error. Called from the
    /// no-images path.
    private func observeCompletionState() {
        observationTask?.cancel()
        observationTask = Task {
            await observeCompletionStateAsync()
        }
    }

    private func observeCompletionStateAsync() async {
        for await state in completionViewModel.createCompletionState {
            if Task.isCancelled { break }
            await MainActor.run {
                if let success = state as? ApiResultSuccess<TaskCompletionResponse> {
                    self.isSubmitting = false
                    self.onComplete(success.data?.updatedTask)
                    self.dismiss()
                } else if let error = ApiResultBridge.error(from: state) {
                    self.errorMessage = error.message
                    self.showError = true
                    self.isSubmitting = false
                }
            }
            if state is ApiResultSuccess<TaskCompletionResponse> || ApiResultBridge.isError(state) {
                break
            }
        }
    }

}

// Helper extension to convert Data to KotlinByteArray
extension KotlinByteArray {
    convenience init(data: Data) {
        let array = [UInt8](data)
        self.init(size: Int32(array.count))
        for (index, byte) in array.enumerated() {
            self.set(index: Int32(index), value: Int8(bitPattern: byte))
        }
    }
}

// MARK: - Contractor Picker View
struct ContractorPickerView: View {
    @Environment(\.dismiss) private var dismiss
    @Binding var selectedContractor: ContractorSummary?
    @ObservedObject var contractorViewModel: ContractorViewModel

    var body: some View {
        NavigationStack {
            List {
                // None option
                Button(action: {
                    selectedContractor = nil
                    dismiss()
                }) {
                    HStack {
                        VStack(alignment: .leading) {
                            Text(L10n.Tasks.noneManual)
                                .foregroundColor(Color.appTextPrimary)
                            Text(L10n.Tasks.enterManually)
                                .font(.caption)
                                .foregroundColor(Color.appTextSecondary)
                        }
                        Spacer()
                        if selectedContractor == nil {
                            Image(systemName: "checkmark")
                                .foregroundColor(Color.appPrimary)
                        }
                    }
                }
                .sectionBackground()

                // Contractors list
                if contractorViewModel.isLoading {
                    HStack {
                        Spacer()
                        ProgressView()
                            .tint(Color.appPrimary)
                        Spacer()
                    }
                    .sectionBackground()
                } else if let errorMessage = contractorViewModel.errorMessage {
                    Text(errorMessage)
                        .foregroundColor(Color.appError)
                        .font(.caption)
                        .sectionBackground()
                } else {
                    ForEach(contractorViewModel.contractors, id: \.id) { contractor in
                        Button(action: {
                            selectedContractor = contractor
                            dismiss()
                        }) {
                            HStack {
                                VStack(alignment: .leading, spacing: 4) {
                                    Text(contractor.name)
                                        .foregroundColor(Color.appTextPrimary)

                                    if let company = contractor.company {
                                        Text(company)
                                            .font(.caption)
                                            .foregroundColor(Color.appTextSecondary)
                                    }

                                    if let firstSpecialty = contractor.specialties.first {
                                        HStack(spacing: 4) {
                                            Image(systemName: "wrench.and.screwdriver")
                                                .font(.caption2)
                                            Text(firstSpecialty.name)
                                                .font(.caption2)
                                        }
                                        .foregroundColor(Color.appTextSecondary.opacity(0.7))
                                    }
                                }

                                Spacer()

                                if selectedContractor?.id == contractor.id {
                                    Image(systemName: "checkmark")
                                        .foregroundColor(Color.appPrimary)
                                }
                            }
                        }
                        .sectionBackground()
                    }
                }
            }
            .standardFormStyle()
            .background(WarmGradientBackground())
            .navigationTitle(L10n.Tasks.selectContractor)
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button(L10n.Common.cancel) {
                        dismiss()
                    }
                }
            }
        }
    }
}
