//
//  PhotoEditorView.swift
//  CheapRetouch
//
//  Main editor view composing canvas, toolbar, and coordinating edit operations.
//

import SwiftUI
import PhotosUI
import UIKit
import UniformTypeIdentifiers

struct PhotoEditorView: View {
    @State private var viewModel = EditorViewModel()
    @State private var selectedItem: PhotosPickerItem?
    @State private var isShowingPicker = false
    @State private var isShowingExport = false
    @State private var isShowingDocumentPicker = false
    @State private var isShowingImportOptions = false
    @Environment(\.accessibilityReduceMotion) private var reduceMotion

    var body: some View {
        NavigationStack {
            ZStack {
                Color.black
                    .ignoresSafeArea()

                if viewModel.originalImage != nil {
                    VStack(spacing: 0) {
                        CanvasView(viewModel: viewModel)

                        if viewModel.showingMaskConfirmation {
                            maskConfirmationBar
                        }

                        ToolbarView(viewModel: viewModel)
                    }
                } else {
                    EmptyStateView(isShowingPicker: $isShowingPicker)
                }

                // Processing overlay
                if viewModel.isProcessing {
                    processingOverlay
                }

                // Error toast
                if let error = viewModel.errorMessage {
                    errorToast(message: error)
                }
            }
            .navigationTitle("CheapRetouch")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarLeading) {
                    Menu {
                        Button {
                            isShowingPicker = true
                        } label: {
                            Label("Photo Library", systemImage: "photo.on.rectangle")
                        }

                        Button {
                            isShowingDocumentPicker = true
                        } label: {
                            Label("Files", systemImage: "folder")
                        }
                    } label: {
                        Image(systemName: "photo.on.rectangle")
                    }
                    .disabled(viewModel.isProcessing)
                    .accessibilityLabel("Import photo")
                    .accessibilityHint("Opens options to import from Photo Library or Files")
                }

                if viewModel.originalImage != nil {
                    ToolbarItem(placement: .topBarTrailing) {
                        Button {
                            isShowingExport = true
                        } label: {
                            Image(systemName: "square.and.arrow.up")
                        }
                        .disabled(viewModel.isProcessing || viewModel.displayImage == nil)
                    }
                }
            }
            .onChange(of: selectedItem) { oldValue, newValue in
                Task {
                    guard let item = newValue else { return }

                    // Get localIdentifier if available
                    let localIdentifier = item.itemIdentifier

                    if let data = try? await item.loadTransferable(type: Data.self),
                       let uiImage = UIImage(data: data) {
                        viewModel.loadImage(uiImage, localIdentifier: localIdentifier)
                    }
                    
                    // Reset selection so the same image can be selected again
                    selectedItem = nil
                }
            }
            .photosPicker(isPresented: $isShowingPicker, selection: $selectedItem, matching: .images)
            .sheet(isPresented: $isShowingExport) {
                if let image = viewModel.displayImage {
                    ExportView(image: image)
                }
            }
            .sheet(isPresented: $isShowingDocumentPicker) {
                DocumentPickerView { result in
                    handleDocumentPickerResult(result)
                }
            }
        }
    }

    private func handleDocumentPickerResult(_ result: Result<URL, Error>) {
        switch result {
        case .success(let url):
            guard url.startAccessingSecurityScopedResource() else {
                viewModel.errorMessage = "Unable to access file"
                return
            }
            defer { url.stopAccessingSecurityScopedResource() }

            do {
                let data = try Data(contentsOf: url)
                guard let uiImage = UIImage(data: data) else {
                    viewModel.errorMessage = "Unable to load image"
                    return
                }

                // Check for large images
                let pixelCount = Int(uiImage.size.width * uiImage.scale * uiImage.size.height * uiImage.scale)
                if pixelCount > 48_000_000 {
                    viewModel.errorMessage = "Image is very large (48MP+). May cause memory issues."
                } else if pixelCount > 12_000_000 {
                    viewModel.errorMessage = "Large image detected. Processing may take longer."
                }

                viewModel.loadImage(uiImage)
            } catch {
                viewModel.errorMessage = "Failed to load image: \(error.localizedDescription)"
            }

        case .failure(let error):
            if (error as NSError).code != NSUserCancelledError {
                viewModel.errorMessage = "Failed to import: \(error.localizedDescription)"
            }
        }
    }

    private var maskConfirmationBar: some View {
        VStack(spacing: 12) {
            // Low confidence warning
            if viewModel.isLowConfidenceMask {
                HStack {
                    Image(systemName: "exclamationmark.triangle.fill")
                        .foregroundStyle(.yellow)
                    Text("Does this look right? The selection may need refinement.")
                        .font(.caption)
                        .foregroundStyle(.secondary)
                }
                .padding(.horizontal, 12)
                .padding(.vertical, 8)
                .background(Color.yellow.opacity(0.1), in: RoundedRectangle(cornerRadius: 8))
                .accessibilityElement(children: .combine)
                .accessibilityLabel("Warning: Low confidence detection. The selection may need refinement.")
            }

            // High contrast toggle for accessibility
            HStack {
                Toggle(isOn: $viewModel.useHighContrastMask) {
                    Label("High Contrast", systemImage: "circle.lefthalf.filled")
                        .font(.caption)
                }
                .toggleStyle(.button)
                .buttonStyle(.bordered)
                .accessibilityLabel("High contrast mask")
                .accessibilityHint("Toggle to use colorblind-friendly cyan color for mask preview")

                Spacer()

                if viewModel.showSelectAllPeople && viewModel.detectedPeopleCount > 1 {
                    Button {
                        Task {
                            await viewModel.selectAllPeople()
                        }
                    } label: {
                        Label("Select All \(viewModel.detectedPeopleCount)", systemImage: "person.3.fill")
                            .font(.caption)
                    }
                    .buttonStyle(.bordered)
                    .accessibilityLabel("Select all \(viewModel.detectedPeopleCount) detected people")
                }
            }

            HStack(spacing: 12) {
                Button {
                    viewModel.cancelMask()
                } label: {
                    Label("Cancel", systemImage: "xmark")
                        .font(.headline)
                        .frame(maxWidth: .infinity)
                        .padding(.vertical, 12)
                }
                .buttonStyle(.bordered)
                .tint(.secondary)
                .accessibilityLabel("Cancel mask selection")

                Button {
                    Task {
                        await viewModel.confirmMask()
                    }
                } label: {
                    Label("Remove", systemImage: "trash")
                        .font(.headline)
                        .frame(maxWidth: .infinity)
                        .padding(.vertical, 12)
                }
                .buttonStyle(.borderedProminent)
                .tint(.red)
                .accessibilityLabel("Confirm and remove selected area")
            }
        }
        .padding()
        .background(.ultraThinMaterial)
    }

    private var processingOverlay: some View {
        VStack(spacing: 12) {
            ProgressView()
                .scaleEffect(1.2)

            if !viewModel.processingMessage.isEmpty {
                Text(viewModel.processingMessage)
                    .font(.subheadline)
                    .foregroundStyle(.secondary)
            }
        }
        .padding(24)
        .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 16))
        .accessibilityElement(children: .combine)
        .accessibilityLabel("Processing: \(viewModel.processingMessage)")
        .accessibilityAddTraits(.updatesFrequently)
    }

    private func errorToast(message: String) -> some View {
        VStack {
            Spacer()

            HStack {
                Image(systemName: "exclamationmark.triangle.fill")
                    .foregroundStyle(.yellow)
                Text(message)
                    .font(.subheadline)
            }
            .padding()
            .background(.ultraThinMaterial, in: RoundedRectangle(cornerRadius: 12))
            .padding()
            .padding(.bottom, 80)
            .accessibilityElement(children: .combine)
            .accessibilityLabel("Error: \(message)")
            .accessibilityAddTraits(.isStaticText)
        }
        .transition(reduceMotion ? .opacity : .move(edge: .bottom).combined(with: .opacity))
        .onAppear {
            // Announce error for VoiceOver
            UIAccessibility.post(notification: .announcement, argument: "Error: \(message)")
            Task {
                try? await Task.sleep(for: .seconds(3))
                viewModel.errorMessage = nil
            }
        }
    }
}

// MARK: - Document Picker

struct DocumentPickerView: UIViewControllerRepresentable {
    let onResult: (Result<URL, Error>) -> Void

    func makeUIViewController(context: Context) -> UIDocumentPickerViewController {
        let picker = UIDocumentPickerViewController(forOpeningContentTypes: [
            UTType.jpeg,
            UTType.png,
            UTType.heic,
            UTType.image
        ])
        picker.delegate = context.coordinator
        picker.allowsMultipleSelection = false
        return picker
    }

    func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {}

    func makeCoordinator() -> Coordinator {
        Coordinator(onResult: onResult)
    }

    class Coordinator: NSObject, UIDocumentPickerDelegate {
        let onResult: (Result<URL, Error>) -> Void

        init(onResult: @escaping (Result<URL, Error>) -> Void) {
            self.onResult = onResult
        }

        func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
            guard let url = urls.first else { return }
            onResult(.success(url))
        }

        func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
            onResult(.failure(NSError(domain: "", code: NSUserCancelledError)))
        }
    }
}

struct EmptyStateView: View {
    @Binding var isShowingPicker: Bool
    @ScaledMetric private var iconSize: CGFloat = 60

    var body: some View {
        VStack(spacing: 20) {
            Image(systemName: "photo.badge.plus")
                .font(.system(size: iconSize))
                .foregroundStyle(.secondary)
                .accessibilityHidden(true)

            Text("No Photo Selected")
                .font(.title2)
                .fontWeight(.medium)

            Text("Import a photo to start removing\nunwanted elements")
                .font(.subheadline)
                .foregroundStyle(.secondary)
                .multilineTextAlignment(.center)

            Button {
                isShowingPicker = true
            } label: {
                Label("Select Photo", systemImage: "photo.on.rectangle")
                    .font(.headline)
                    .padding(.horizontal, 24)
                    .padding(.vertical, 12)
            }
            .buttonStyle(.borderedProminent)
            .padding(.top, 8)
            .accessibilityLabel("Select photo to edit")
            .accessibilityHint("Opens the photo picker to import an image")
        }
        .accessibilityElement(children: .contain)
    }
}

#Preview {
    PhotoEditorView()
}
