package main

import (
	"log"
	"os"
	"os/exec"
	"runtime"
	"strconv"
	"sync/atomic"
	"time"
	"unsafe"

	"github.com/getlantern/systray"
	"github.com/jchv/go-webview2"
)

func onSystrayReady() {
	systray.SetIcon(trayIcon)
	systray.SetTooltip("动态壁纸引擎")

	// 左键点击托盘图标 → 打开设置（防抖: 连续点击只响应一次）
	go func() {
		for range systray.TrayClickCh {
			openSettingsWindow()
			// 消费后续积压的点击
			for {
				select {
				case <-systray.TrayClickCh:
				default:
					goto done
				}
			}
		done:
		}
	}()

	mSettings := systray.AddMenuItem("桌面设置", "打开设置窗口")
	mCheckUpdate := systray.AddMenuItem("检查更新", "检查是否有新版本")
	mRestart := systray.AddMenuItem("重启", "重启程序")
	mQuit := systray.AddMenuItem("退出", "退出程序")

	// 检查更新
	go func() {
		for {
			<-mCheckUpdate.ClickedCh
			manualCheckUpdate()
		}
	}()

	// 设置窗口
	go func() {
		for {
			<-mSettings.ClickedCh
			openSettingsWindow()
		}
	}()

	// 退出
	go func() {
		<-mQuit.ClickedCh
		os.Exit(0)
	}()

	// 重启
	go func() {
		for {
			<-mRestart.ClickedCh
			exe, _ := os.Executable()
			exec.Command(exe).Start()
			os.Exit(0)
		}
	}()

	go startWebView()
	go weatherLoop()
	go horoscopeLoop()
	go aiNewsLoop()
	go bingWallpaperLoop()
	go knowledgeLoop()
	go startPhotoLoop()
	go runAutoUpdateCheck()

	// 音频可视化：启动后检查是否需要音频捕获
	go func() {
		time.Sleep(2 * time.Second)
		cfg := loadConfig()
		if cfg.WallpaperType == WPTheme && cfg.Theme == ThemeAudioViz {
			startAudioCapture()
		}
	}()
}

func startWebView() {
	runtime.LockOSThread()
	log.Println("startWebView: 开始")

	workerw := findWorkerW()
	if workerw == 0 {
		log.Println("ERROR: WorkerW not found")
		showError("无法找到桌面窗口（WorkerW），程序无法启动。")
		os.Exit(1)
	}
	log.Printf("WorkerW: 0x%x", workerw)

	screenW, screenH := getScreenSize()
	log.Printf("Screen: %dx%d", screenW, screenH)

	log.Println("创建 WebView2...")
	wv = webview2.NewWithOptions(webview2.WebViewOptions{
		AutoFocus: false,
		WindowOptions: webview2.WindowOptions{
			Title:  "动态壁纸",
			Width:  uint(screenW),
			Height: uint(screenH),
		},
	})
	if wv == nil {
		showError("WebView2 创建失败，请确保已安装 WebView2 Runtime。")
		os.Exit(1)
	}
	log.Println("WebView2 创建成功")

	// 立即获取 HWND 并隐藏窗口，避免闪烁
	wvHwnd = uintptr(wv.Window())
	procShowWindow.Call(wvHwnd, 0) // SW_HIDE
	procSetWindowLongPtrW.Call(wvHwnd, gwlStyle, wsPopup|wsVisible|wsChild)
	procSetWindowLongPtrW.Call(wvHwnd, gwlExStyle, wsExTransparent|wsExLayered)

	// 立即嵌入 WorkerW
	embedWorkerW(workerw, screenW, screenH)
	log.Printf("已嵌入 WorkerW: HWND=0x%x, %dx%d", wvHwnd, screenW, screenH)

	wv.Bind("setZodiacFromGo", func(zodiac string) error {
		cfg := loadConfig()
		cfg.Zodiac = zodiac
		return saveConfig(cfg)
	})

	log.Println("设置 HTML...")
	cfg := loadConfig()
	wv.SetHtml(buildWallpaperHTML(cfg))
	time.Sleep(500 * time.Millisecond)

	// 嵌入完成后再显示
	procShowWindow.Call(wvHwnd, 5)
	log.Println("壁纸窗口已显示")

	go func() {
		time.Sleep(500 * time.Millisecond)
		reloadAllCards()
	}()

	go fullscreenMonitor()

	type msg struct {
		hwnd    uintptr
		message uint32
		wParam  uintptr
		lParam  uintptr
		time    uint32
		pt      struct{ x, y int32 }
	}
	var m msg
	for {
		ret, _, _ := procGetMessageW.Call(
			uintptr(unsafe.Pointer(&m)),
			0, 0, 0,
		)
		if ret == 0 {
			break
		}
		if m.message == wmEvalJS {
			for {
				select {
				case js := <-jsQueue:
					wv.Eval(js)
				default:
					goto nextMsg
				}
			}
		}
		if m.message == wmSetHtml {
			select {
			case html := <-htmlQueue:
				wv.SetHtml(html)
			default:
			}
			goto nextMsg
		}
	nextMsg:
		procTranslateMessage.Call(uintptr(unsafe.Pointer(&m)))
		procDispatchMessageW.Call(uintptr(unsafe.Pointer(&m)))
	}
}

func embedWorkerW(workerw uintptr, screenW, screenH int32) {
	procSetParent.Call(wvHwnd, workerw)
	procMoveWindow.Call(wvHwnd, uintptr(^uint(0)), uintptr(^uint(0)), uintptr(screenW+2), uintptr(screenH+2), 1)
}

func fullscreenMonitor() {
	type rect struct{ Left, Top, Right, Bottom int32 }
	var lastState string
	var lastParent uintptr
	var parentTick int
	for {
		if atomic.LoadInt32(&paused) == 0 && wv != nil {
			// 每 5 轮(10s)检测一次父窗口，极轻量系统调用
			parentTick++
			if parentTick >= 5 {
				parentTick = 0
				parent, _, _ := procGetParent.Call(wvHwnd)
				if parent != lastParent {
					lastParent = parent
					ww := findWorkerW()
					if ww != 0 && ww != parent {
						screenW, screenH := getScreenSize()
						embedWorkerW(ww, screenW, screenH)
						procShowWindow.Call(wvHwnd, 5)
						log.Printf("WorkerW 变更，已重新嵌入: 0x%x → 0x%x", parent, ww)
					}
				}
			}

			fg, _, _ := procGetForegroundWindow.Call()
			if fg != 0 {
				var r rect
				procGetWindowRect.Call(fg, uintptr(unsafe.Pointer(&r)))
				screenW, screenH := getScreenSize()
				isFull := (r.Right-r.Left >= screenW) && (r.Bottom-r.Top >= screenH)
				state := strconv.FormatBool(isFull)
				if state != lastState {
					lastState = state
					evalJS("if(window.setFullscreen) setFullscreen(" + state + ")")
				}
			}
		}
		time.Sleep(2 * time.Second)
	}
}
