package desktop

import (
	"log"
	"runtime"
	"sync"
	"time"
	"unsafe"
)

// InputController - Klavye ve mouse kontrol servisi
type InputController struct {
	mu              sync.RWMutex
	isEnabled       bool
	mousePosition   MousePosition
	keyboardLayout  string
	modifierState   ModifierState
	lastInputTime   time.Time
	inputQueue      chan InputEvent
	stopChan        chan struct{}
}

// MousePosition - Mouse pozisyonu
type MousePosition struct {
	X int `json:"x"`
	Y int `json:"y"`
}

// ModifierState - Modifier tuş durumları
type ModifierState struct {
	Shift   bool `json:"shift"`
	Ctrl    bool `json:"ctrl"`
	Alt     bool `json:"alt"`
	Meta    bool `json:"meta"` // Windows tuşu
	CapsLock bool `json:"capsLock"`
	NumLock  bool `json:"numLock"`
}

// InputEvent - Giriş olayı
type InputEvent struct {
	Type      string      `json:"type"`      // "mouse", "keyboard", "scroll"
	Action    string      `json:"action"`    // "move", "click", "down", "up", "press", "scroll"
	Data      interface{} `json:"data"`      // İlgili veri
	Timestamp int64       `json:"timestamp"` // Unix timestamp (ms)
}

// MouseEvent - Mouse olayı
type MouseEvent struct {
	X        int    `json:"x"`
	Y        int    `json:"y"`
	Button   string `json:"button"`   // "left", "right", "middle"
	Clicks   int    `json:"clicks"`   // Tıklama sayısı (çift tık için 2)
	DeltaX   int    `json:"deltaX"`   // Scroll için
	DeltaY   int    `json:"deltaY"`   // Scroll için
	Relative bool   `json:"relative"` // Göreceli hareket mi
}

// KeyboardEvent - Klavye olayı
type KeyboardEvent struct {
	Key       string `json:"key"`       // Tuş adı
	Code      string `json:"code"`      // Fiziksel tuş kodu
	KeyCode   int    `json:"keyCode"`   // Virtual key code
	Char      string `json:"char"`      // Karakter (varsa)
	Shift     bool   `json:"shift"`
	Ctrl      bool   `json:"ctrl"`
	Alt       bool   `json:"alt"`
	Meta      bool   `json:"meta"`
	Repeat    bool   `json:"repeat"`    // Tekrar basılı mı
	Location  int    `json:"location"`  // 0=standard, 1=left, 2=right, 3=numpad
}

// Windows API yapıları
type POINT struct {
	X, Y int32
}

type INPUT struct {
	Type uint32
	Mi   MOUSEINPUT
}

type MOUSEINPUT struct {
	Dx          int32
	Dy          int32
	MouseData   uint32
	DwFlags     uint32
	Time        uint32
	DwExtraInfo uintptr
}

type KEYBDINPUT struct {
	WVk         uint16
	WScan       uint16
	DwFlags     uint32
	Time        uint32
	DwExtraInfo uintptr
}

// Windows API sabitleri
const (
	INPUT_MOUSE    = 0
	INPUT_KEYBOARD = 1

	// Mouse flags
	MOUSEEVENTF_MOVE       = 0x0001
	MOUSEEVENTF_LEFTDOWN   = 0x0002
	MOUSEEVENTF_LEFTUP     = 0x0004
	MOUSEEVENTF_RIGHTDOWN  = 0x0008
	MOUSEEVENTF_RIGHTUP    = 0x0010
	MOUSEEVENTF_MIDDLEDOWN = 0x0020
	MOUSEEVENTF_MIDDLEUP   = 0x0040
	MOUSEEVENTF_WHEEL      = 0x0800
	MOUSEEVENTF_HWHEEL     = 0x1000
	MOUSEEVENTF_ABSOLUTE   = 0x8000

	// Keyboard flags
	KEYEVENTF_KEYUP       = 0x0002
	KEYEVENTF_UNICODE     = 0x0004
	KEYEVENTF_SCANCODE    = 0x0008
	KEYEVENTF_EXTENDEDKEY = 0x0001

	// Scroll
	WHEEL_DELTA = 120
)

// Virtual Key Codes (Windows)
var VKCodes = map[string]uint16{
	// Modifier keys
	"Shift":       0x10,
	"ShiftLeft":   0xA0,
	"ShiftRight":  0xA1,
	"Control":     0x11,
	"ControlLeft": 0xA2,
	"ControlRight": 0xA3,
	"Alt":         0x12,
	"AltLeft":     0xA4,
	"AltRight":    0xA5,
	"Meta":        0x5B, // Windows key left
	"MetaLeft":    0x5B,
	"MetaRight":   0x5C,
	"CapsLock":    0x14,
	"NumLock":     0x90,
	"ScrollLock":  0x91,

	// Function keys
	"F1":  0x70,
	"F2":  0x71,
	"F3":  0x72,
	"F4":  0x73,
	"F5":  0x74,
	"F6":  0x75,
	"F7":  0x76,
	"F8":  0x77,
	"F9":  0x78,
	"F10": 0x79,
	"F11": 0x7A,
	"F12": 0x7B,
	"F13": 0x7C,
	"F14": 0x7D,
	"F15": 0x7E,
	"F16": 0x7F,
	"F17": 0x80,
	"F18": 0x81,
	"F19": 0x82,
	"F20": 0x83,
	"F21": 0x84,
	"F22": 0x85,
	"F23": 0x86,
	"F24": 0x87,

	// Navigation keys
	"Escape":     0x1B,
	"Tab":        0x09,
	"Backspace":  0x08,
	"Enter":      0x0D,
	"Space":      0x20,
	"Insert":     0x2D,
	"Delete":     0x2E,
	"Home":       0x24,
	"End":        0x23,
	"PageUp":     0x21,
	"PageDown":   0x22,
	"ArrowUp":    0x26,
	"ArrowDown":  0x28,
	"ArrowLeft":  0x25,
	"ArrowRight": 0x27,
	"PrintScreen": 0x2C,
	"Pause":      0x13,
	"ContextMenu": 0x5D,

	// Numpad
	"Numpad0":        0x60,
	"Numpad1":        0x61,
	"Numpad2":        0x62,
	"Numpad3":        0x63,
	"Numpad4":        0x64,
	"Numpad5":        0x65,
	"Numpad6":        0x66,
	"Numpad7":        0x67,
	"Numpad8":        0x68,
	"Numpad9":        0x69,
	"NumpadMultiply": 0x6A,
	"NumpadAdd":      0x6B,
	"NumpadSubtract": 0x6D,
	"NumpadDecimal":  0x6E,
	"NumpadDivide":   0x6F,
	"NumpadEnter":    0x0D,

	// Alphabet (A-Z)
	"KeyA": 0x41, "KeyB": 0x42, "KeyC": 0x43, "KeyD": 0x44,
	"KeyE": 0x45, "KeyF": 0x46, "KeyG": 0x47, "KeyH": 0x48,
	"KeyI": 0x49, "KeyJ": 0x4A, "KeyK": 0x4B, "KeyL": 0x4C,
	"KeyM": 0x4D, "KeyN": 0x4E, "KeyO": 0x4F, "KeyP": 0x50,
	"KeyQ": 0x51, "KeyR": 0x52, "KeyS": 0x53, "KeyT": 0x54,
	"KeyU": 0x55, "KeyV": 0x56, "KeyW": 0x57, "KeyX": 0x58,
	"KeyY": 0x59, "KeyZ": 0x5A,

	// Numbers (0-9)
	"Digit0": 0x30, "Digit1": 0x31, "Digit2": 0x32, "Digit3": 0x33,
	"Digit4": 0x34, "Digit5": 0x35, "Digit6": 0x36, "Digit7": 0x37,
	"Digit8": 0x38, "Digit9": 0x39,

	// Symbols
	"Minus":        0xBD, // -
	"Equal":        0xBB, // =
	"BracketLeft":  0xDB, // [
	"BracketRight": 0xDD, // ]
	"Backslash":    0xDC, // \
	"Semicolon":    0xBA, // ;
	"Quote":        0xDE, // '
	"Backquote":    0xC0, // `
	"Comma":        0xBC, // ,
	"Period":       0xBE, // .
	"Slash":        0xBF, // /
	"IntlBackslash": 0xE2, // International backslash

	// Media keys
	"MediaPlayPause":    0xB3,
	"MediaStop":         0xB2,
	"MediaTrackPrevious": 0xB1,
	"MediaTrackNext":    0xB0,
	"AudioVolumeMute":   0xAD,
	"AudioVolumeDown":   0xAE,
	"AudioVolumeUp":     0xAF,

	// Browser keys
	"BrowserBack":     0xA6,
	"BrowserForward":  0xA7,
	"BrowserRefresh":  0xA8,
	"BrowserStop":     0xA9,
	"BrowserSearch":   0xAA,
	"BrowserFavorites": 0xAB,
	"BrowserHome":     0xAC,
}

// Windows API tanımlamaları winapi.go'da

// NewInputController - Yeni input controller
func NewInputController() *InputController {
	return &InputController{
		isEnabled:    true,
		inputQueue:   make(chan InputEvent, 100),
		stopChan:     make(chan struct{}),
		modifierState: ModifierState{},
	}
}

// Enable - Input kontrolünü etkinleştir
func (ic *InputController) Enable() {
	ic.mu.Lock()
	defer ic.mu.Unlock()
	ic.isEnabled = true
	log.Println("Input kontrolü etkinleştirildi")
}

// Disable - Input kontrolünü devre dışı bırak
func (ic *InputController) Disable() {
	ic.mu.Lock()
	defer ic.mu.Unlock()
	ic.isEnabled = false
	log.Println("Input kontrolü devre dışı bırakıldı")
}

// IsEnabled - Input kontrolü aktif mi
func (ic *InputController) IsEnabled() bool {
	ic.mu.RLock()
	defer ic.mu.RUnlock()
	return ic.isEnabled
}

// GetMousePosition - Mouse pozisyonunu al
func (ic *InputController) GetMousePosition() MousePosition {
	if runtime.GOOS != "windows" {
		return MousePosition{X: 0, Y: 0}
	}

	var pt POINT
	procGetCursorPos.Call(uintptr(unsafe.Pointer(&pt)))
	return MousePosition{X: int(pt.X), Y: int(pt.Y)}
}

// MoveMouse - Mouse'u hareket ettir
func (ic *InputController) MoveMouse(x, y int, relative bool) error {
	if !ic.IsEnabled() {
		return nil
	}

	if runtime.GOOS != "windows" {
		return nil
	}

	if relative {
		// Göreceli hareket
		procMouse_event.Call(
			MOUSEEVENTF_MOVE,
			uintptr(x),
			uintptr(y),
			0,
			0,
		)
	} else {
		// Mutlak pozisyon
		procSetCursorPos.Call(uintptr(x), uintptr(y))
	}

	ic.mu.Lock()
	ic.mousePosition = MousePosition{X: x, Y: y}
	ic.lastInputTime = time.Now()
	ic.mu.Unlock()

	return nil
}

// MouseClick - Mouse tıklama
func (ic *InputController) MouseClick(button string, clicks int, x, y int) error {
	if !ic.IsEnabled() {
		return nil
	}

	if runtime.GOOS != "windows" {
		return nil
	}

	// Önce mouse'u pozisyona taşı
	if x >= 0 && y >= 0 {
		ic.MoveMouse(x, y, false)
		time.Sleep(10 * time.Millisecond)
	}

	var downFlag, upFlag uintptr
	switch button {
	case "right":
		downFlag = MOUSEEVENTF_RIGHTDOWN
		upFlag = MOUSEEVENTF_RIGHTUP
	case "middle":
		downFlag = MOUSEEVENTF_MIDDLEDOWN
		upFlag = MOUSEEVENTF_MIDDLEUP
	default: // left
		downFlag = MOUSEEVENTF_LEFTDOWN
		upFlag = MOUSEEVENTF_LEFTUP
	}

	if clicks <= 0 {
		clicks = 1
	}

	for i := 0; i < clicks; i++ {
		procMouse_event.Call(downFlag, 0, 0, 0, 0)
		time.Sleep(10 * time.Millisecond)
		procMouse_event.Call(upFlag, 0, 0, 0, 0)
		if i < clicks-1 {
			time.Sleep(50 * time.Millisecond) // Çift tık için bekleme
		}
	}

	ic.mu.Lock()
	ic.lastInputTime = time.Now()
	ic.mu.Unlock()

	return nil
}

// MouseDown - Mouse tuşu basılı
func (ic *InputController) MouseDown(button string) error {
	if !ic.IsEnabled() || runtime.GOOS != "windows" {
		return nil
	}

	var flag uintptr
	switch button {
	case "right":
		flag = MOUSEEVENTF_RIGHTDOWN
	case "middle":
		flag = MOUSEEVENTF_MIDDLEDOWN
	default:
		flag = MOUSEEVENTF_LEFTDOWN
	}

	procMouse_event.Call(flag, 0, 0, 0, 0)
	return nil
}

// MouseUp - Mouse tuşu bırakıldı
func (ic *InputController) MouseUp(button string) error {
	if !ic.IsEnabled() || runtime.GOOS != "windows" {
		return nil
	}

	var flag uintptr
	switch button {
	case "right":
		flag = MOUSEEVENTF_RIGHTUP
	case "middle":
		flag = MOUSEEVENTF_MIDDLEUP
	default:
		flag = MOUSEEVENTF_LEFTUP
	}

	procMouse_event.Call(flag, 0, 0, 0, 0)
	return nil
}

// MouseScroll - Mouse scroll
func (ic *InputController) MouseScroll(deltaX, deltaY int) error {
	if !ic.IsEnabled() || runtime.GOOS != "windows" {
		return nil
	}

	// Vertical scroll
	if deltaY != 0 {
		procMouse_event.Call(
			MOUSEEVENTF_WHEEL,
			0,
			0,
			uintptr(deltaY*WHEEL_DELTA),
			0,
		)
	}

	// Horizontal scroll
	if deltaX != 0 {
		procMouse_event.Call(
			MOUSEEVENTF_HWHEEL,
			0,
			0,
			uintptr(deltaX*WHEEL_DELTA),
			0,
		)
	}

	return nil
}

// KeyPress - Tuşa bas ve bırak
func (ic *InputController) KeyPress(event KeyboardEvent) error {
	if !ic.IsEnabled() || runtime.GOOS != "windows" {
		return nil
	}

	// Modifier tuşları önce bas
	if event.Ctrl {
		ic.keyDown(0x11, 0) // VK_CONTROL
	}
	if event.Shift {
		ic.keyDown(0x10, 0) // VK_SHIFT
	}
	if event.Alt {
		ic.keyDown(0x12, 0) // VK_MENU
	}
	if event.Meta {
		ic.keyDown(0x5B, 0) // VK_LWIN
	}

	// Ana tuşu bul ve bas
	vk := ic.getVKCode(event)
	if vk > 0 {
		ic.keyDown(vk, 0)
		time.Sleep(10 * time.Millisecond)
		ic.keyUp(vk, 0)
	} else if event.Char != "" {
		// Unicode karakter gönder
		ic.typeUnicode(event.Char)
	}

	// Modifier tuşları bırak
	if event.Meta {
		ic.keyUp(0x5B, 0)
	}
	if event.Alt {
		ic.keyUp(0x12, 0)
	}
	if event.Shift {
		ic.keyUp(0x10, 0)
	}
	if event.Ctrl {
		ic.keyUp(0x11, 0)
	}

	ic.mu.Lock()
	ic.lastInputTime = time.Now()
	ic.mu.Unlock()

	return nil
}

// KeyDown - Tuşu basılı tut
func (ic *InputController) KeyDown(event KeyboardEvent) error {
	if !ic.IsEnabled() || runtime.GOOS != "windows" {
		return nil
	}

	vk := ic.getVKCode(event)
	if vk > 0 {
		ic.keyDown(vk, 0)
	}

	// Modifier durumunu güncelle
	ic.updateModifierState(event, true)
	return nil
}

// KeyUp - Tuşu bırak
func (ic *InputController) KeyUp(event KeyboardEvent) error {
	if !ic.IsEnabled() || runtime.GOOS != "windows" {
		return nil
	}

	vk := ic.getVKCode(event)
	if vk > 0 {
		ic.keyUp(vk, 0)
	}

	// Modifier durumunu güncelle
	ic.updateModifierState(event, false)
	return nil
}

// TypeText - Metin yaz
func (ic *InputController) TypeText(text string, delay int) error {
	if !ic.IsEnabled() || runtime.GOOS != "windows" {
		return nil
	}

	if delay <= 0 {
		delay = 10
	}

	for _, char := range text {
		ic.typeUnicode(string(char))
		time.Sleep(time.Duration(delay) * time.Millisecond)
	}

	return nil
}

// SendKeyCombination - Tuş kombinasyonu gönder (örn: Ctrl+Alt+Delete)
func (ic *InputController) SendKeyCombination(keys []string) error {
	if !ic.IsEnabled() || runtime.GOOS != "windows" {
		return nil
	}

	// Tüm tuşları bas
	for _, key := range keys {
		if vk, ok := VKCodes[key]; ok {
			ic.keyDown(vk, 0)
			time.Sleep(10 * time.Millisecond)
		}
	}

	// Tüm tuşları bırak (ters sırada)
	for i := len(keys) - 1; i >= 0; i-- {
		if vk, ok := VKCodes[keys[i]]; ok {
			ic.keyUp(vk, 0)
			time.Sleep(10 * time.Millisecond)
		}
	}

	return nil
}

// getVKCode - Virtual key code al
func (ic *InputController) getVKCode(event KeyboardEvent) uint16 {
	// Önce Code ile dene
	if event.Code != "" {
		if vk, ok := VKCodes[event.Code]; ok {
			return vk
		}
	}

	// Key ile dene
	if event.Key != "" {
		if vk, ok := VKCodes[event.Key]; ok {
			return vk
		}

		// Tek karakter ise ASCII değerini kullan
		if len(event.Key) == 1 {
			char := rune(event.Key[0])
			if char >= 'a' && char <= 'z' {
				return uint16(char - 32) // Büyük harfe çevir
			}
			if char >= 'A' && char <= 'Z' {
				return uint16(char)
			}
			if char >= '0' && char <= '9' {
				return uint16(char)
			}
		}
	}

	// KeyCode ile dene
	if event.KeyCode > 0 {
		return uint16(event.KeyCode)
	}

	return 0
}

// keyDown - Windows keybd_event down
func (ic *InputController) keyDown(vk uint16, scan uint16) {
	procKeybd_event.Call(
		uintptr(vk),
		uintptr(scan),
		0,
		0,
	)
}

// keyUp - Windows keybd_event up
func (ic *InputController) keyUp(vk uint16, scan uint16) {
	procKeybd_event.Call(
		uintptr(vk),
		uintptr(scan),
		KEYEVENTF_KEYUP,
		0,
	)
}

// typeUnicode - Unicode karakter gönder
func (ic *InputController) typeUnicode(text string) {
	for _, char := range text {
		// Key down
		procKeybd_event.Call(
			0,
			uintptr(char),
			KEYEVENTF_UNICODE,
			0,
		)
		// Key up
		procKeybd_event.Call(
			0,
			uintptr(char),
			KEYEVENTF_UNICODE|KEYEVENTF_KEYUP,
			0,
		)
	}
}

// updateModifierState - Modifier durumunu güncelle
func (ic *InputController) updateModifierState(event KeyboardEvent, down bool) {
	ic.mu.Lock()
	defer ic.mu.Unlock()

	switch event.Code {
	case "ShiftLeft", "ShiftRight", "Shift":
		ic.modifierState.Shift = down
	case "ControlLeft", "ControlRight", "Control":
		ic.modifierState.Ctrl = down
	case "AltLeft", "AltRight", "Alt":
		ic.modifierState.Alt = down
	case "MetaLeft", "MetaRight", "Meta":
		ic.modifierState.Meta = down
	case "CapsLock":
		if down {
			ic.modifierState.CapsLock = !ic.modifierState.CapsLock
		}
	case "NumLock":
		if down {
			ic.modifierState.NumLock = !ic.modifierState.NumLock
		}
	}
}

// GetModifierState - Modifier durumunu al
func (ic *InputController) GetModifierState() ModifierState {
	ic.mu.RLock()
	defer ic.mu.RUnlock()
	return ic.modifierState
}

// GetScreenSize - Ekran boyutunu al
func (ic *InputController) GetScreenSize() (int, int) {
	if runtime.GOOS != "windows" {
		return 1920, 1080 // Varsayılan
	}

	const SM_CXSCREEN = 0
	const SM_CYSCREEN = 1

	width, _, _ := procGetSystemMetrics.Call(SM_CXSCREEN)
	height, _, _ := procGetSystemMetrics.Call(SM_CYSCREEN)

	return int(width), int(height)
}

// ProcessInputEvent - Gelen input event'ini işle
func (ic *InputController) ProcessInputEvent(event InputEvent) error {
	switch event.Type {
	case "mouse":
		return ic.processMouseEvent(event)
	case "keyboard":
		return ic.processKeyboardEvent(event)
	case "scroll":
		return ic.processScrollEvent(event)
	}
	return nil
}

func (ic *InputController) processMouseEvent(event InputEvent) error {
	data, ok := event.Data.(map[string]interface{})
	if !ok {
		return nil
	}

	x := int(data["x"].(float64))
	y := int(data["y"].(float64))
	button := "left"
	if b, ok := data["button"].(string); ok {
		button = b
	}
	clicks := 1
	if c, ok := data["clicks"].(float64); ok {
		clicks = int(c)
	}

	switch event.Action {
	case "move":
		relative := false
		if r, ok := data["relative"].(bool); ok {
			relative = r
		}
		return ic.MoveMouse(x, y, relative)
	case "click":
		return ic.MouseClick(button, clicks, x, y)
	case "down":
		return ic.MouseDown(button)
	case "up":
		return ic.MouseUp(button)
	}

	return nil
}

func (ic *InputController) processKeyboardEvent(event InputEvent) error {
	data, ok := event.Data.(map[string]interface{})
	if !ok {
		return nil
	}

	keyEvent := KeyboardEvent{
		Key:     getString(data, "key"),
		Code:    getString(data, "code"),
		KeyCode: getInt(data, "keyCode"),
		Char:    getString(data, "char"),
		Shift:   getBool(data, "shift"),
		Ctrl:    getBool(data, "ctrl"),
		Alt:     getBool(data, "alt"),
		Meta:    getBool(data, "meta"),
		Repeat:  getBool(data, "repeat"),
	}

	switch event.Action {
	case "press":
		return ic.KeyPress(keyEvent)
	case "down":
		return ic.KeyDown(keyEvent)
	case "up":
		return ic.KeyUp(keyEvent)
	}

	return nil
}

func (ic *InputController) processScrollEvent(event InputEvent) error {
	data, ok := event.Data.(map[string]interface{})
	if !ok {
		return nil
	}

	deltaX := getInt(data, "deltaX")
	deltaY := getInt(data, "deltaY")

	return ic.MouseScroll(deltaX, deltaY)
}

// Helper fonksiyonları
func getString(m map[string]interface{}, key string) string {
	if v, ok := m[key].(string); ok {
		return v
	}
	return ""
}

func getInt(m map[string]interface{}, key string) int {
	if v, ok := m[key].(float64); ok {
		return int(v)
	}
	return 0
}

func getBool(m map[string]interface{}, key string) bool {
	if v, ok := m[key].(bool); ok {
		return v
	}
	return false
}
