import SwiftUI
import PhotosUI
import os.log
import AVKit

struct MediaPickerWithLogging: UIViewControllerRepresentable {
    @Binding var selectedMedia: [MediaType]
    let selectionLimit: Int
    let onDismiss: (() -> Void)?
    
    func makeUIViewController(context: Context) -> PHPickerViewController {
        var configuration = PHPickerConfiguration(photoLibrary: PHPhotoLibrary.shared())
        configuration.filter = .any(of: [.videos, .images])
        configuration.selectionLimit = selectionLimit
        configuration.preferredAssetRepresentationMode = .current
        
        let picker = PHPickerViewController(configuration: configuration)
        picker.delegate = context.coordinator
        return picker
    }
    
    func updateUIViewController(_ uiViewController: PHPickerViewController, context: Context) {}
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, PHPickerViewControllerDelegate {
        let parent: MediaPickerWithLogging
        private let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "com.example.app", category: "MediaPickerWithLogging")
        
        init(_ parent: MediaPickerWithLogging) {
            self.parent = parent
        }
        
        func picker(_ picker: PHPickerViewController, didFinishPicking results: [PHPickerResult]) {
            guard !results.isEmpty else {
                parent.onDismiss?()
                return
            }
            
            var processedMedia: [MediaType] = []
            let group = DispatchGroup()
            
            for result in results {
                let itemProvider = result.itemProvider
                
                if itemProvider.hasItemConformingToTypeIdentifier(UTType.image.identifier) {
                    group.enter()
                    processImage(itemProvider: itemProvider) { media in
                        if let media = media {
                            processedMedia.append(media)
                        }
                        group.leave()
                    }
                } else if itemProvider.hasItemConformingToTypeIdentifier(UTType.movie.identifier) {
                    group.enter()
                    processVideo(itemProvider: itemProvider) { media in
                        if let media = media {
                            processedMedia.append(media)
                        }
                        group.leave()
                    }
                }
            }
            
            group.notify(queue: .main) {
                self.parent.selectedMedia = processedMedia
                self.printMediaInfo(media: processedMedia)
                self.parent.onDismiss?()
            }
        }
        
        private func processImage(itemProvider: NSItemProvider, completion: @escaping (MediaType?) -> Void) {
            itemProvider.loadObject(ofClass: UIImage.self) { (object, error) in
                if let image = object as? UIImage {
                    completion(.image(image))
                } else {
                    self.logger.error("Failed to load image: \(error?.localizedDescription ?? "Unknown error")")
                    completion(nil)
                }
            }
        }
        
        private func processVideo(itemProvider: NSItemProvider, completion: @escaping (MediaType?) -> Void) {
            itemProvider.loadFileRepresentation(forTypeIdentifier: UTType.movie.identifier) { url, error in
                guard let videoURL = url, error == nil else {
                    self.logger.error("Failed to load video: \(error?.localizedDescription ?? "Unknown error")")
                    completion(nil)
                    return
                }
                
                let tempDirectory = FileManager.default.temporaryDirectory
                let targetURL = tempDirectory.appendingPathComponent("\(UUID().uuidString).\(videoURL.pathExtension)")
                
                do {
                    if FileManager.default.fileExists(atPath: targetURL.path) {
                        try FileManager.default.removeItem(at: targetURL)
                    }
                    try FileManager.default.copyItem(at: videoURL, to: targetURL)
                    
                    MediaUtils.extractFirstFrame(from: targetURL) { result in
                        switch result {
                        case .success(let thumbnail):
                            completion(.video(targetURL, thumbnail))
                        case .failure(let error):
                            self.logger.error("Failed to extract video thumbnail: \(error.localizedDescription)")
                            completion(.video(targetURL, nil))
                        }
                    }
                } catch {
                    self.logger.error("Failed to copy video file: \(error.localizedDescription)")
                    completion(nil)
                }
            }
        }
        
        private func printMediaInfo(media: [MediaType]) {
            print("=== Selected Media Information ===")
            for (index, media) in media.enumerated() {
                print("\nItem \(index + 1):")
                
                switch media {
                case .image(let image):
                    print("Type: Image")
                    print("Dimensions: \(Int(image.size.width))x\(Int(image.size.height))")
                    if let data = image.jpegData(compressionQuality: 1.0) {
                        print("File Size: \(formatFileSize(Int64(data.count)))")
                    }
                    
                case .video(let url, _):
                    print("Type: Video")
                    print("File Name: \(url.lastPathComponent)")
                    print("File Path: \(url.path)")
                    
                    if let attributes = try? FileManager.default.attributesOfItem(atPath: url.path),
                       let fileSize = attributes[.size] as? Int64 {
                        print("File Size: \(formatFileSize(fileSize))")
                    }
                    
                    let asset = AVURLAsset(url: url)
                    let duration = asset.duration.seconds
                    print("Duration: \(formatTimeInterval(duration))")
                    
                    if let track = asset.tracks(withMediaType: .video).first {
                        let size = track.naturalSize
                        print("Video Dimensions: \(Int(size.width))x\(Int(size.height))")
                    }
                }
            }
            print("================================\n")
        }
        
        private func formatFileSize(_ bytes: Int64) -> String {
            let formatter = ByteCountFormatter()
            formatter.allowedUnits = [.useBytes, .useKB, .useMB, .useGB]
            formatter.countStyle = .file
            return formatter.string(fromByteCount: bytes)
        }
        
        private func formatTimeInterval(_ interval: TimeInterval) -> String {
            let formatter = DateComponentsFormatter()
            formatter.allowedUnits = [.hour, .minute, .second]
            formatter.zeroFormattingBehavior = .pad
            return formatter.string(from: interval) ?? "00:00"
        }
    }
}