//
//  ShareViewController.swift
//  Haystack
//
//  Created by Rio Keefe on 03/05/2025.
//

import UIKit
import Social
import MobileCoreServices // For kUTTypeImage

class ShareViewController: SLComposeServiceViewController {

    let appGroupName = "group.com.haystack.app" // Replace with your actual App Group identifier
    let tokenKey = "sharedAuthToken"
    let uploadURLBase = URL(string: "https://haystack.johncosta.tech/image/")! // Base URL

    var bearerToken: String?
    private var imageItemProvider: NSItemProvider?
    // Store a base name, extension will be determined during item loading
    private var baseImageName: String = "SharedImage" // A more descriptive default

    override func viewDidLoad() {
        super.viewDidLoad()

        if let sharedDefaults = UserDefaults(suiteName: appGroupName) {
            bearerToken = sharedDefaults.string(forKey: tokenKey)
            print("Retrieved bearer token: \(bearerToken ?? "nil")")
        } else {
            print("Error accessing App Group UserDefaults.")
            // Invalidate content if token is crucial and missing
            // This will be caught by isContentValid()
        }

        guard let extensionItem = extensionContext?.inputItems.first as? NSExtensionItem,
              let provider = extensionItem.attachments?.first else {
            print("No attachments found.")
            // Invalidate content if no provider
            self.imageItemProvider = nil // Ensure it's nil so isContentValid fails
            return
        }

        if provider.hasItemConformingToTypeIdentifier(kUTTypeImage as String) {
            self.imageItemProvider = provider
            // Attempt to get a suggested name early if available, and clean it.
            // This will be our default base name if the item itself doesn't provide a better one.
            if let suggested = provider.suggestedName, !suggested.isEmpty {
                if let dotRange = suggested.range(of: ".", options: .backwards) {
                    self.baseImageName = String(suggested[..<dotRange.lowerBound])
                } else {
                    self.baseImageName = suggested
                }
            }
            // Sanitize the base name slightly (remove problematic characters for a filename)
            let anInvalidCharacters = CharacterSet(charactersIn: "/\\?%*|\"<>:")
            self.baseImageName = self.baseImageName.components(separatedBy: anInvalidCharacters).joined(separator: "_")
            if self.baseImageName.isEmpty { self.baseImageName = "SharedImage" } // Ensure not empty

        } else {
            print("Attachment is not an image.")
            self.imageItemProvider = nil // Ensure it's nil so isContentValid fails
        }
    }

    override func isContentValid() -> Bool {
        // Content is valid only if we have an item provider for an image AND a bearer token
        let isValid = imageItemProvider != nil && bearerToken != nil
        if imageItemProvider == nil {
            print("isContentValid: imageItemProvider is nil")
        }
        if bearerToken == nil {
            print("isContentValid: bearerToken is nil")
        }
        return isValid
    }

    override func didSelectPost() {
        guard let provider = imageItemProvider else {
            print("Error: No image item provider found when posting.")
            informUserAndCancel(message: "No image found to share.")
            return
        }

        guard let token = bearerToken else {
            print("Error: Bearer token is missing when posting.")
            informUserAndCancel(message: "Authentication error. Please try again.")
            return
        }

        // Start activity indicator or similar UI feedback
        // For SLComposeServiceViewController, the system provides some UI

        provider.loadItem(forTypeIdentifier: kUTTypeImage as String, options: nil) { [weak self] (item, error) in
            guard let self = self else { return }

            if let error = error {
                print("Error loading image data for upload: \(error.localizedDescription)")
                self.informUserAndCancel(message: "Could not load image: \(error.localizedDescription)")
                return
            }

            var imageData: Data?
            var finalImageNameWithExtension: String
            var mimeType: String = "application/octet-stream" // Default MIME type

            // Determine base name (without extension)
            var currentBaseName = self.baseImageName // Use the one prepared in viewDidLoad
            if let suggested = provider.suggestedName, !suggested.isEmpty {
                 if let dotRange = suggested.range(of: ".", options: .backwards) {
                    currentBaseName = String(suggested[..<dotRange.lowerBound])
                } else {
                    currentBaseName = suggested
                }
                let anInvalidCharacters = CharacterSet(charactersIn: "/\\?%*|\"<>:")
                currentBaseName = currentBaseName.components(separatedBy: anInvalidCharacters).joined(separator: "_")
                if currentBaseName.isEmpty { currentBaseName = "DefaultImageName" }
            }


            if let url = item as? URL {
                print("Image provided as URL: \(url)")
                finalImageNameWithExtension = url.lastPathComponent // Includes extension
                // Ensure baseName is updated if URL provides a different one
                if let dotRange = finalImageNameWithExtension.range(of:".", options: .backwards) {
                    currentBaseName = String(finalImageNameWithExtension[..<dotRange.lowerBound])
                } else {
                    currentBaseName = finalImageNameWithExtension // No extension in name
                }

                do {
                    imageData = try Data(contentsOf: url)
                    // Determine MIME type from URL extension
                    let pathExtension = url.pathExtension.lowercased()
                    mimeType = self.mimeType(forPathExtension: pathExtension)
                    if !finalImageNameWithExtension.contains(".") && !pathExtension.isEmpty { // if original lastPathComponent had no ext
                        finalImageNameWithExtension = "\(currentBaseName).\(pathExtension)"
                    } else if !finalImageNameWithExtension.contains(".") && pathExtension.isEmpty { // no ext anywhere
                         finalImageNameWithExtension = "\(currentBaseName).jpg" // default to jpg
                         mimeType = "image/jpeg"
                    }

                } catch {
                    print("Error creating Data from URL: \(error)")
                    self.informUserAndCancel(message: "Could not read image file.")
                    return
                }
            } else if let image = item as? UIImage {
                print("Image provided as UIImage")
                // Prefer PNG for screenshots/UIImage, fallback to JPEG
                if let data = image.pngData() {
                    imageData = data
                    mimeType = "image/png"
                    finalImageNameWithExtension = "\(currentBaseName).png"
                } else if let data = image.jpegData(compressionQuality: 0.9) { // Good quality JPEG
                    imageData = data
                    mimeType = "image/jpeg"
                    finalImageNameWithExtension = "\(currentBaseName).jpg"
                } else {
                    print("Could not convert UIImage to Data.")
                    self.informUserAndCancel(message: "Could not process image.")
                    return
                }
            } else if let data = item as? Data {
                print("Image provided as Data")
                imageData = data
                // We have raw data, try to use suggestedName's extension or default to png/jpg
                var determinedExtension = "png" // Default
                if let suggested = provider.suggestedName,
                   let dotRange = suggested.range(of: ".", options: .backwards) {
                    let ext = String(suggested[dotRange.upperBound...]).lowercased()
                    if ["png", "jpg", "jpeg", "gif"].contains(ext) {
                        determinedExtension = ext
                    }
                }
                mimeType = self.mimeType(forPathExtension: determinedExtension)
                finalImageNameWithExtension = "\(currentBaseName).\(determinedExtension)"

            } else {
                print("Error: Could not get image data in a usable format. Item type: \(type(of: item)) Item: \(String(describing: item))")
                self.informUserAndCancel(message: "Unsupported image format.")
                return
            }

            guard let dataToUpload = imageData else {
                print("Error: No image data to upload after processing.")
                self.informUserAndCancel(message: "Image data is missing.")
                return
            }
            
            // Ensure finalImageNameWithExtension is not just an extension like ".png"
            if finalImageNameWithExtension.starts(with: ".") {
                finalImageNameWithExtension = "\(self.baseImageName)\(finalImageNameWithExtension)"
            }
            if finalImageNameWithExtension.isEmpty || !finalImageNameWithExtension.contains(".") {
                // Fallback if somehow the name is bad
                finalImageNameWithExtension = "\(self.baseImageName).png"
                mimeType = "image/png"
            }

            print("Uploading image: \(finalImageNameWithExtension), MIME: \(mimeType), Size: \(dataToUpload.count) bytes")
            self.uploadRawData(dataToUpload, imageNameWithExtension: finalImageNameWithExtension, mimeType: mimeType, bearerToken: token)
        }
    }

    func uploadRawData(_ rawData: Data, imageNameWithExtension: String, mimeType: String, bearerToken: String) {
        // The imageNameWithExtension should already include the correct extension.
        // The server URL seems to expect the filename as a path component.
        let uploadURL = uploadURLBase.appendingPathComponent(imageNameWithExtension)
        print("Final Upload URL: \(uploadURL.absoluteString)")

        var request = URLRequest(url: uploadURL)
        request.httpMethod = "POST"
        request.httpBody = rawData
        request.setValue(mimeType, forHTTPHeaderField: "Content-Type") // Use determined MIME type
        request.setValue("Bearer \(bearerToken)", forHTTPHeaderField: "Authorization")
        request.setValue("\(rawData.count)", forHTTPHeaderField: "Content-Length")


        let task = URLSession.shared.dataTask(with: request) { [weak self] (data, response, error) in
            DispatchQueue.main.async {
                guard let self = self else { return }
                print("Upload finished. Error: \(error?.localizedDescription ?? "None")")
                if let httpResponse = response as? HTTPURLResponse {
                    print("HTTP Status: \(httpResponse.statusCode)")
                    if let responseData = data, let responseString = String(data: responseData, encoding: .utf8) {
                        print("Response Data: \(responseString)")
                    }
                }


                if let error = error {
                    print("Upload failed: \(error.localizedDescription)")
                    self.informUserAndCancel(message: "Upload failed: \(error.localizedDescription)")
                } else if let httpResponse = response as? HTTPURLResponse, !(200...299).contains(httpResponse.statusCode) {
                    let errorDescription = "Upload failed. Server returned status code \(httpResponse.statusCode)."
                    print(errorDescription)
                    self.informUserAndCancel(message: errorDescription)
                } else {
                    print("Upload successful for \(imageNameWithExtension)")
                    self.extensionContext!.completeRequest(returningItems: [], completionHandler: nil)
                }
            }
        }
        task.resume()
    }

    override func configurationItems() -> [Any]! {
        // No configuration items needed for this simple image uploader.
        return []
    }

    // Helper to inform user and cancel request
    private func informUserAndCancel(message: String) {
        let error = NSError(domain: "com.haystack.ShareExtension", code: 0, userInfo: [NSLocalizedDescriptionKey: message])
        print("Informing user: \(message)")
        // You could present an alert here if SLComposeServiceViewController allows easy alert presentation.
        // For now, just cancel the request. The system might show a generic error.
        self.extensionContext!.cancelRequest(withError: error)
    }

    // Helper to get MIME type from path extension
    private func mimeType(forPathExtension pathExtension: String) -> String {
        let uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, pathExtension as CFString, nil)?.takeRetainedValue()
        if let uti = uti {
            let mimeType = UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType)?.takeRetainedValue()
            if let mimeType = mimeType {
                return mimeType as String
            }
        }
        // Fallback for common types if UTType fails or for robustness
        switch pathExtension.lowercased() {
            // case "jpg", "jpeg": return "image/jpeg"
            // case "png": return "image/png"
            // case "gif": return "image/gif"
            // case "bmp": return "image/bmp"
            // case "tiff", "tif": return "image/tiff"
            default: return "application/octet-stream" // Generic fallback
        }
    }
}
