import Cocoa
import ApplicationServices

class AccessibilityHelper {
    
    /// Check if the currently focused element is a text input field
    static func isTextFieldFocused() -> (isFocused: Bool, element: AXUIElement?) {
        // Get the frontmost application
        guard let frontmostApp = NSWorkspace.shared.frontmostApplication else {
            return (false, nil)
        }
        
        let appElement = AXUIElementCreateApplication(frontmostApp.processIdentifier)
        
        // Get focused element
        var focusedElement: CFTypeRef?
        let result = AXUIElementCopyAttributeValue(appElement, kAXFocusedUIElementAttribute as CFString, &focusedElement)
        
        guard result == .success, let element = focusedElement else {
            return (false, nil)
        }
        
        let axElement = element as! AXUIElement
        
        // Check if it's a text field or text area
        var roleValue: CFTypeRef?
        AXUIElementCopyAttributeValue(axElement, kAXRoleAttribute as CFString, &roleValue)
        
        if let role = roleValue as? String {
            let textFieldRoles = [
                kAXTextFieldRole as String,
                kAXTextAreaRole as String,
                kAXComboBoxRole as String,
                "AXTextField",
                "AXTextArea",
                "AXWebArea" // For web-based text fields
            ]
            
            if textFieldRoles.contains(role) {
                return (true, axElement)
            }
            
            // Check subrole for web text fields
            var subroleValue: CFTypeRef?
            AXUIElementCopyAttributeValue(axElement, kAXSubroleAttribute as CFString, &subroleValue)
            if let subrole = subroleValue as? String, subrole.contains("Text") {
                return (true, axElement)
            }
        }
        
        return (false, nil)
    }
    
    /// Insert text at the current cursor position
    static func insertText(_ text: String, into element: AXUIElement) {
        // Get current value
        var currentValue: CFTypeRef?
        AXUIElementCopyAttributeValue(element, kAXValueAttribute as CFString, &currentValue)
        
        let existingText = (currentValue as? String) ?? ""
        
        // Get selected text range if available
        var selectedRangeValue: CFTypeRef?
        let rangeResult = AXUIElementCopyAttributeValue(element, kAXSelectedTextRangeAttribute as CFString, &selectedRangeValue)
        
        var insertPosition = existingText.count
        var replaceLength = 0
        
        if rangeResult == .success, let rangeValue = selectedRangeValue {
            var range = CFRange()
            AXValueGetValue(rangeValue as! AXValue, .cfRange, &range)
            insertPosition = range.location
            replaceLength = range.length
        }
        
        // Build new text
        let prefix = String(existingText.prefix(insertPosition))
        let suffix = String(existingText.dropFirst(insertPosition + replaceLength))
        let newText = prefix + text + suffix
        
        // Set the new value
        AXUIElementSetAttributeValue(element, kAXValueAttribute as CFString, newText as CFString)
        
        // Set cursor position after inserted text
        let newCursorPosition = insertPosition + text.count
        var newRange = CFRange(location: newCursorPosition, length: 0)
        if let rangeValue = AXValueCreate(.cfRange, &newRange) {
            AXUIElementSetAttributeValue(element, kAXSelectedTextRangeAttribute as CFString, rangeValue)
        }
    }
    
    /// Type text using keyboard events (fallback method)
    static func typeText(_ text: String) {
        let source = CGEventSource(stateID: .hidSystemState)
        
        for char in text {
            let keyCode = char.keyCode
            if let keyDownEvent = CGEvent(keyboardEventSource: source, virtualKey: keyCode, keyDown: true),
               let keyUpEvent = CGEvent(keyboardEventSource: source, virtualKey: keyCode, keyDown: false) {
                keyDownEvent.post(tap: .cghidEventTap)
                keyUpEvent.post(tap: .cghidEventTap)
            }
        }
    }
    
    /// Simulate Command+V paste keyboard shortcut
    @discardableResult
    static func pasteText() -> Bool {
        print("⌨️  Simulating Command+V paste...")
        
        let source = CGEventSource(stateID: .combinedSessionState)
        
        // Create Command key down event first
        guard let cmdDown = CGEvent(keyboardEventSource: source, virtualKey: 0x37, keyDown: true) else {
            print("❌ Failed to create Command down event")
            return false
        }
        cmdDown.flags = .maskCommand
        
        // Create V key down with Command flag
        guard let keyVDown = CGEvent(keyboardEventSource: source, virtualKey: 0x09, keyDown: true) else {
            print("❌ Failed to create V down event")
            return false
        }
        keyVDown.flags = .maskCommand
        
        // Create V key up with Command flag
        guard let keyVUp = CGEvent(keyboardEventSource: source, virtualKey: 0x09, keyDown: false) else {
            print("❌ Failed to create V up event")
            return false
        }
        keyVUp.flags = .maskCommand
        
        // Create Command key up event
        guard let cmdUp = CGEvent(keyboardEventSource: source, virtualKey: 0x37, keyDown: false) else {
            print("❌ Failed to create Command up event")
            return false
        }
        
        // Post events in sequence: Cmd down -> V down -> V up -> Cmd up
        cmdDown.post(tap: .cghidEventTap)
        Thread.sleep(forTimeInterval: 0.02) // 20ms
        
        keyVDown.post(tap: .cghidEventTap)
        Thread.sleep(forTimeInterval: 0.02) // 20ms
        
        keyVUp.post(tap: .cghidEventTap)
        Thread.sleep(forTimeInterval: 0.02) // 20ms
        
        cmdUp.post(tap: .cghidEventTap)
        
        print("✅ Command+V sequence posted (4 events)")
        return true
    }
}

// Helper extension for character to key code mapping
extension Character {
    var keyCode: CGKeyCode {
        switch self.lowercased() {
        case "a": return 0x00
        case "b": return 0x0B
        case "c": return 0x08
        case "d": return 0x02
        case "e": return 0x0E
        case "f": return 0x03
        case "g": return 0x05
        case "h": return 0x04
        case "i": return 0x22
        case "j": return 0x26
        case "k": return 0x28
        case "l": return 0x25
        case "m": return 0x2E
        case "n": return 0x2D
        case "o": return 0x1F
        case "p": return 0x23
        case "q": return 0x0C
        case "r": return 0x0F
        case "s": return 0x01
        case "t": return 0x11
        case "u": return 0x20
        case "v": return 0x09
        case "w": return 0x0D
        case "x": return 0x07
        case "y": return 0x10
        case "z": return 0x06
        case " ": return 0x31
        case ".": return 0x2F
        case ",": return 0x2B
        default: return 0x31 // Space as fallback
        }
    }
}





