import ExpoModulesCore
import UIKit

public class ImageEditorUIModule: Module {
    public func definition() -> ModuleDefinition {
        Name("ImageEditorUI")

        View(ImageEditorUIComponent.self) {
            Events(
                "onReady",
                "onImageLoaded",
                "onImageChanged",
                "onExport",
                "onError",
                "onClose"
            )

            Prop("source") { (view: ImageEditorUIComponent, source: [String: Any]?) in
                if let source = source {
                    view.loadImage(source: source)
                }
            }

            Prop("config") { (view: ImageEditorUIComponent, configDict: [String: Any]?) in
                if let configDict = configDict {
                    view.updateConfiguration(configDict: configDict)
                }
            }

            AsyncFunction("loadImage") { (view: ImageEditorUIComponent, source: [String: Any]) in
                view.loadImage(source: source)
            }

            AsyncFunction("updateConfig") { (view: ImageEditorUIComponent, configDict: [String: Any]) in
                view.updateConfiguration(configDict: configDict)
            }

            AsyncFunction("getCurrentImage") { (view: ImageEditorUIComponent) -> [String: Any] in
                return try await view.getCurrentImageAsync()
            }
        }
    }
}

// MARK: - View Component

public class ImageEditorUIComponent: ExpoView {

    // MARK: - Properties
    private var viewController: ImageEditorUIViewController?
    private var config: ImageEditorUIConfig = ImageEditorUIConfig()

    // Event callbacks - initialized by Expo Modules
    var onReady: EventDispatcher?
    var onImageLoaded: EventDispatcher?
    var onImageChanged: EventDispatcher?
    var onExport: EventDispatcher?
    var onError: EventDispatcher?
    var onClose: EventDispatcher?

    // MARK: - Initialization
    override required init(appContext: AppContext? = nil) {
        super.init(appContext: appContext)
    }

    public override func didMoveToSuperview() {
        super.didMoveToSuperview()

        if superview != nil && viewController == nil {
            setupViewController()
        }
    }

    // MARK: - Setup
    private func setupViewController() {
        let vc = ImageEditorUIViewController(config: config)
        vc.delegate = self
        viewController = vc

        // Get the parent view controller to add as child
        if let parentVC = findViewController() {
            parentVC.addChild(vc)
            vc.didMove(toParent: parentVC)
        }

        // Add view controller's view to this view
        if let vcView = vc.view {
            vcView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
            addSubview(vcView)
            vcView.frame = bounds
        }

        // Notify that view is ready
        DispatchQueue.main.async { [weak self] in
            self?.onReady?([:])
        }
    }

    public override func layoutSubviews() {
        super.layoutSubviews()
        viewController?.view.frame = bounds
    }

    deinit {
        // Clean up view controller when view is deallocated
        if let vc = viewController {
            vc.willMove(toParent: nil)
            vc.view.removeFromSuperview()
            vc.removeFromParent()
        }
    }

    // Helper to find the parent view controller
    private func findViewController() -> UIViewController? {
        var responder: UIResponder? = self
        while responder != nil {
            responder = responder?.next
            if let viewController = responder as? UIViewController {
                return viewController
            }
        }
        return nil
    }

    // MARK: - Public Methods (called from React Native via ref)
    public func loadImage(source: [String: Any]) {
        guard let viewController = viewController else { return }

        // Parse image source and load directly
        if let uri = source["uri"] as? String {
            if uri.hasPrefix("file://") {
                let path = uri.replacingOccurrences(of: "file://", with: "")
                viewController.loadImage(from: path)
            } else if uri.hasPrefix("http://") || uri.hasPrefix("https://") {
                if let url = URL(string: uri) {
                    // Load from URL
                    DispatchQueue.global(qos: .userInitiated).async { [weak self, weak viewController] in
                        guard let self = self, let viewController = viewController else { return }
                        do {
                            let data = try Data(contentsOf: url)
                            if let image = UIImage(data: data) {
                                DispatchQueue.main.async {
                                    viewController.engine.loadImage(image)
                                }
                            } else {
                                DispatchQueue.main.async {
                                    self.sendError(message: "Failed to decode image from URL")
                                }
                            }
                        } catch {
                            DispatchQueue.main.async {
                                self.sendError(message: "Failed to load image from URL: \(error.localizedDescription)")
                            }
                        }
                    }
                } else {
                    sendError(message: "Invalid URL: \(uri)")
                    return
                }
            } else {
                sendError(message: "Unsupported URI scheme: \(uri)")
                return
            }
        } else {
            sendError(message: "Image source must contain 'uri' property")
        }
    }

    public func updateConfiguration(configDict: [String: Any]) {
        do {
            let data = try JSONSerialization.data(withJSONObject: configDict)
            let decoder = JSONDecoder()
            config = try decoder.decode(ImageEditorUIConfig.self, from: data)
            viewController?.updateConfig(config)
        } catch {
            sendError(message: "Failed to parse configuration: \(error.localizedDescription)")
        }
    }

    public func getCurrentImage(callback: @escaping (String?) -> Void) {
        // Export current image to temp file and return path
        guard let viewController = viewController else {
            callback(nil)
            return
        }

        DispatchQueue.global(qos: .userInitiated).async {
            do {
                let exportFormat: ExportFormat = .jpeg
                let options = ImageEditorEngine.ExportOptions(
                    format: exportFormat,
                    quality: 0.9,
                    maxDimension: nil as Int?
                )

                let data = try viewController.engine.export(options: options)
                let tempURL = FileManager.default.temporaryDirectory
                    .appendingPathComponent("current_image.jpg")

                try data.write(to: tempURL)

                DispatchQueue.main.async {
                    callback(tempURL.path)
                }
            } catch {
                DispatchQueue.main.async {
                    callback(nil)
                }
            }
        }
    }

    // MARK: - Async Methods
    public func getCurrentImageAsync() async throws -> [String: Any] {
        return try await withCheckedThrowingContinuation { continuation in
            getCurrentImage { path in
                if let path = path {
                    continuation.resume(returning: [
                        "uri": "file://\(path)",
                        "path": path
                    ])
                } else {
                    continuation.resume(throwing: NSError(domain: "ImageEditor", code: -1, userInfo: [NSLocalizedDescriptionKey: "Failed to export image"]))
                }
            }
        }
    }

    // MARK: - Helper Methods
    private func sendError(message: String) {
        onError?(["error": message])
    }
}

// MARK: - ImageEditorUIDelegate
extension ImageEditorUIComponent: ImageEditorUIDelegate {
    public func imageEditorDidLoad(_ controller: ImageEditorUIViewController) {
        onReady?([:])
    }

    public func imageEditorDidChange(_ controller: ImageEditorUIViewController) {
        onImageChanged?([:])
    }

    public func imageEditorDidExport(_ controller: ImageEditorUIViewController, fileURL: URL) {
        onExport?([
            "uri": "file://\(fileURL.path)",
            "path": fileURL.path
        ])
    }

    public func imageEditorDidError(_ controller: ImageEditorUIViewController, error: Error) {
        onError?([
            "error": error.localizedDescription
        ])
    }

    public func imageEditorDidClose(_ controller: ImageEditorUIViewController) {
        onClose?([:])
    }
}

