package lxrod

import (
	"context"
	"encoding/base64"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"os"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"git.listensoft.net/tool/jspkit/common/lxhttp"
	"git.listensoft.net/tool/jspkit/common/variable"
	"git.listensoft.net/tool/jspkit/taxerr"
	"github.com/go-rod/rod"
	"github.com/go-rod/rod/lib/launcher"
	"github.com/go-rod/rod/lib/proto"
	"github.com/go-rod/rod/lib/utils"
	"github.com/go-rod/stealth"
)

var (
	LastAlertMsg = make(chan string, 100)
)

// 只允许task.go 初始化一次
type Lxrod struct {
	Area                  variable.Area
	Browser               *rod.Browser
	Launcher              *launcher.Launcher
	NoByPass              bool //添加反反爬虫代码 原理就是执行一段js去掉window属性中关于自动化的代码
	Headless              bool //headless 默认显示浏览器 为true是不显示浏览器
	MonitorDialog         bool //默认监控alert然后去点击true 如果要自己处理 设置为true不添加监控
	PageEvent             bool //默认每个页面的监听事件 设置为true不添加监控
	UseProxy              bool //代理
	Leakless              bool
	NoDefaultDevice       bool
	Proxy                 string
	ProxyAuth             string
	WsURL                 string // rod的ws地址
	NoEachEventForCreated bool
	LoginErrImg           string
}

// 关闭浏览器 统一控制
func (lr *Lxrod) CloseBrowser() (err error) {
	if lr.Browser != nil {
		return rod.Try(func() {
			if lr.Browser != nil {
				lr.Browser.Close()
				go rod.Try(func() {

					lr.Launcher.Cleanup()
					lr.Launcher.Kill()

				})
			}
		})
	}
	return nil
}

// 关闭浏览器 统一控制
func (lr *Lxrod) CloseBrowserNew() {
	if lr.Browser != nil {
		_ = lr.Browser.Close()

		lr.Launcher.Cleanup()

	}
}

func GetAlertMsg() string {

	select {
	case v := <-LastAlertMsg:

		return v
	case <-time.After(time.Second * 8):

		return ""
	}
}

func ClickDialog(p *rod.Page, h func(bool, string)) { //默认添加点击alert事件
	go func() {
		defer func() {
			if err := recover(); err != nil {

				rod.Try(func() { h(true, "确定") })
			}
		}()
		h(true, "确定") //dialog 浏览器语言中文默认是确定 alert浏览器语言英文默认是ok
	}()
}

// 监听 alert confirm 等事件打开
func DialogWatch(ctx context.Context, page *rod.Page) {

	defer func() {
		if r := recover(); r != nil {

		}
	}()
	_, h := page.MustHandleDialog()
	go page.EachEvent(func(e *proto.PageJavascriptDialogOpening) {
		defer func() {

			if r := recover(); r != nil {

			}
		}()
		if strings.Contains(page.MustInfo().URL, `henan`) {
			if strings.Contains(e.Message, `请重新登录`) || strings.Contains(e.Message, `访问异常`) {
				page.Browser().MustSetCookies()

				page.MustNavigate("")

			}
		}
		if strings.Contains(page.MustInfo().URL, `jiangxi`) {
			if strings.Contains(e.Message, "纳税人识别号未注册电子税务局") {

				//LastAlertMsgJiangXi <- e.Message
			}
		}

		LastAlertMsg <- e.Message

		ClickDialog(page, h)
		utils.Sleep(5)
		if len(LastAlertMsg) > 0 {
			_ = <-LastAlertMsg
		} else {

		}

	})()
}

// 新建浏览器对象-青岛
func (lxrod *Lxrod) Newqd(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
	rod.Try(func() {
		lxrod.CloseBrowser()
	})
	utils.Sleep(1)
	lxrod.Launcher = launcher.New()
	lxrod.Launcher.Set("window-size", "1600,900").
		Set("no-sandbox").
		Set("ignore-certificate-errors").
		Set("ignore-certificate-errors-spki-list").
		Set("ignore-ssl-errors").
		Set("disable-features", "CalculateNativeWinOcclusion").
		Headless(lxrod.Headless)
	//lxrod.Launcher.UserDataDir("user-data")
	//if viper.GetString("env") == string(variable.Development) {
	//	lxrod.Launcher.Leakless(false) //开发环境不使用用leakless
	//}
	lxrod.Launcher.Flags["disable-blink-features"] = []string{"AutomationControlled"}
	u, err := lxrod.Launcher.Launch()
	if err != nil {

		err = taxerr.New("调用浏览器失败,请稍后重试！")
		return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
	}
	b = rod.New().ControlURL(u).MustConnect().Context(ctx).NoDefaultDevice() //.Trace(true) Trace调试打开
	utils.Sleep(1)
	b.MustSetCookies()
	p = b.MustPage("").MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
	lxrod.Browser = b
	return lxrod.Browser, p, err
}

// 新建浏览器对象
func (lxrod *Lxrod) New(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
	rod.Try(func() {
		lxrod.CloseBrowser()
	})
	utils.Sleep(1)
	// if viper.GetString("env") == string(variable.Development) { //直接启动浏览器
	lxrod.Launcher = launcher.New()
	// } else { //容器内启动
	// serviceURL := os.Getenv("serviceURL")
	// lxrod.Launcher, err = launcher.NewManaged(serviceURL)
	// if err != nil {
	//
	// err = taxerr.New("调用浏览器失败,请稍后重试！")
	// return lxrod.Browser, p, err
	// }
	// lxrod.Launcher.XVFB("--server-num=5", "--server-args=-screen 0 1600x900x16")
	// }
	lxrod.Launcher.Set("window-size", "1600,900").
		Set("no-sandbox").
		Set("ignore-certificate-errors").
		Set("ignore-certificate-errors-spki-list").
		Set("ignore-ssl-errors").
		Set("disable-features", "CalculateNativeWinOcclusion").
		//UserDataDir("user-data").
		Headless(lxrod.Headless)
	//if lxrod.Area == "hebei" {
	//	lxrod.Launcher.UserDataDir("user-data")
	//}
	//if lxrod.Area == "hebei" {
	lxrod.Launcher.Flags["disable-blink-features"] = []string{"AutomationControlled"}
	//}
	//if viper.GetString("env") == string(variable.Development) {
	//	//lxrod.Launcher.Leakless(false) //开发环境不使用用leakless todo 进程老是结束不掉
	//}
	// Leakless(lxrod.Leakless)
	// chromePath, ok := launcher.LookPath()
	// fmt.Println(ok)
	// fmt.Println(chromePath)
	// if ok {
	// 	lxrod.Launcher.Bin(chromePath)
	// }
	if lxrod.UseProxy {
		lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area))
		lxrod.Launcher.Proxy(lxrod.Proxy)
	}
	u, err := lxrod.Launcher.Launch()
	lxrod.WsURL = u
	if err != nil {
		err = taxerr.New("调用浏览器失败,请稍后重试！")
		return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
	}
	// lxrod.Browser = rod.New().Client(lxrod.Launcher.MustClient()).MustConnect().Context(ctx).MustSetCookies() //.Trace(true) Trace调试打开
	lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx) //.Trace(true) Trace调试打开
	utils.Sleep(1)
	lxrod.Browser.MustSetCookies()
	if lxrod.NoDefaultDevice {
		lxrod.Browser.NoDefaultDevice()
	}
	if !lxrod.NoByPass {
		//是否需要反反爬虫
		p = stealth.MustPage(lxrod.Browser)
	} else {
		p, err = lxrod.Browser.Page(proto.TargetCreateTarget{})
		if err != nil {
			return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
		}
	}
	// launcher.Open(lxrod.Browser.ServeMonitor(""))
	p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
	if lxrod.MonitorDialog {
		DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控
	}
	if !lxrod.PageEvent {
		lxrod.EachPageCreatedEvent(ctx, lxrod.Browser)
	}
	return lxrod.Browser, p, err
}

func (lxrod *Lxrod) NewSd(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
	rod.Try(func() {
		lxrod.CloseBrowser()
	})
	utils.Sleep(1)
	// if viper.GetString("env") == string(variable.Development) { //直接启动浏览器
	lxrod.Launcher = launcher.New()
	// } else { //容器内启动
	// serviceURL := os.Getenv("serviceURL")
	// lxrod.Launcher, err = launcher.NewManaged(serviceURL)
	// if err != nil {
	//
	// err = taxerr.New("调用浏览器失败,请稍后重试！")
	// return lxrod.Browser, p, err
	// }
	// lxrod.Launcher.XVFB("--server-num=5", "--server-args=-screen 0 1600x900x16")
	// }
	lxrod.Launcher.Set("window-size", "1600,900").
		Set("no-sandbox").
		Set("ignore-certificate-errors").
		Set("ignore-certificate-errors-spki-list").
		Set("ignore-ssl-errors").
		Set("disable-features", "CalculateNativeWinOcclusion").
		//UserDataDir("user-data").
		Headless(lxrod.Headless)
	//if viper.GetString("env") == string(variable.Development) {
	//	lxrod.Launcher.Leakless(false) //开发环境不使用用leakless
	//}
	// Leakless(lxrod.Leakless)
	// chromePath, ok := launcher.LookPath()
	// fmt.Println(ok)
	// fmt.Println(chromePath)
	// if ok {
	// 	lxrod.Launcher.Bin(chromePath)
	// }
	if lxrod.UseProxy {
		lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area))
		lxrod.Launcher.Proxy(lxrod.Proxy)
	}
	u, err := lxrod.Launcher.Launch()
	if err != nil {

		err = taxerr.New("调用浏览器失败,请稍后重试！")
		return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
	}
	// lxrod.Browser = rod.New().Client(lxrod.Launcher.MustClient()).MustConnect().Context(ctx).MustSetCookies() //.Trace(true) Trace调试打开
	lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx) //.Trace(true) Trace调试打开
	utils.Sleep(1)
	lxrod.Browser.MustSetCookies()
	if lxrod.NoDefaultDevice {
		lxrod.Browser.NoDefaultDevice()
	}
	if !lxrod.NoByPass {
		//是否需要反反爬虫
		p = stealth.MustPage(lxrod.Browser)
	} else {
		p, err = lxrod.Browser.Page(proto.TargetCreateTarget{})
		if err != nil {
			return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
		}
	}
	// launcher.Open(lxrod.Browser.ServeMonitor(""))
	p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
	if lxrod.MonitorDialog {
		DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控
	}
	lxrod.EachPageCreatedEvent(ctx, lxrod.Browser)
	return lxrod.Browser, p, err
}

// 新建浏览器对象 易代账移除EachPageCreatedEvent否则新标签页打不开 by fengxianwei
func (lxrod *Lxrod) NewByydz(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
	rod.Try(func() {
		lxrod.CloseBrowser()
	})
	utils.Sleep(1)
	// if viper.GetString("env") == string(variable.Development) { //直接启动浏览器
	lxrod.Launcher = launcher.New()
	// } else { //容器内启动
	// serviceURL := os.Getenv("serviceURL")
	// lxrod.Launcher, err = launcher.NewManaged(serviceURL)
	// if err != nil {
	//
	// err = taxerr.New("调用浏览器失败,请稍后重试！")
	// return lxrod.Browser, p, err
	// }
	// lxrod.Launcher.XVFB("--server-num=5", "--server-args=-screen 0 1600x900x16")
	// }
	lxrod.Launcher.Set("window-size", "1600,900").
		Set("no-sandbox").
		Set("ignore-certificate-errors").
		Set("ignore-certificate-errors-spki-list").
		Set("ignore-ssl-errors").
		Set("disable-features", "CalculateNativeWinOcclusion").
		//UserDataDir("user-data").
		Headless(lxrod.Headless)
	//if viper.GetString("env") == string(variable.Development) {
	//	lxrod.Launcher.Leakless(false) //开发环境不使用用leakless
	//}
	if lxrod.UseProxy {
		lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area))
		lxrod.Launcher.Proxy(lxrod.Proxy)
	}
	u, err := lxrod.Launcher.Launch()
	if err != nil {

		err = taxerr.New("调用浏览器失败,请稍后重试！")
		return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
	}
	lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx) //.Trace(true) Trace调试打开
	utils.Sleep(1)
	lxrod.Browser.MustSetCookies()
	if lxrod.NoDefaultDevice {
		lxrod.Browser.NoDefaultDevice()
	}
	if !lxrod.NoByPass {
		//是否需要反反爬虫
		p = stealth.MustPage(lxrod.Browser)
	} else {
		p, err = lxrod.Browser.Page(proto.TargetCreateTarget{})
		if err != nil {
			return lxrod.Browser, p, taxerr.NewWebStuckTitle(true)
		}
	}
	p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
	if lxrod.MonitorDialog {
		DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控
	}
	return lxrod.Browser, p, err
}

// 跳过反爬虫检查
func (lxrod *Lxrod) EachPageCreatedEvent(ctx context.Context, browser *rod.Browser) {
	if !lxrod.MonitorDialog && lxrod.NoByPass {
		return
	}
	go browser.EachEvent(func(e *proto.TargetTargetCreated) {
		defer func() {
			if r := recover(); r != nil {

			}
		}()
		if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
			return
		}
		page := browser.MustPageFromTargetID(e.TargetInfo.TargetID)
		if !lxrod.NoByPass {
			_, err := page.EvalOnNewDocument(stealth.JS)
			if err != nil {
				return
			}
			page.MustEvalOnNewDocument(stealth.JS)
			page.MustSetUserAgent(nil)
			utils.E(proto.RuntimeRunIfWaitingForDebugger{}.Call(page))
		}
		page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
		if lxrod.MonitorDialog {
			DialogWatch(ctx, page) //为新打开的页面添加一个dialog监控
		}
	})()
	utils.E(proto.TargetSetAutoAttach{
		AutoAttach:             true,
		WaitForDebuggerOnStart: true,
		Flatten:                true,
	}.Call(browser))

}

func PageToClient(page *rod.Page, BaseURL string) (*http.Client, error) {
	c := lxhttp.NewHttpClient()
	e := rod.Try(func() {
		cookies := page.MustCookies()
		var cookiesArr []*http.Cookie
		for _, v := range cookies {
			var cookie http.Cookie
			cookie.Name = v.Name
			cookie.Value = v.Value
			cookiesArr = append(cookiesArr, &cookie)
		}
		clientURL, _ := url.Parse(BaseURL)
		c.Jar.SetCookies(clientURL, cookiesArr)
	})
	return c, e
}

func BrowserToClient(b *rod.Browser, BaseURL string) (*http.Client, error) {
	domainMap := map[string][]*http.Cookie{}
	c := lxhttp.NewHttpClient()
	e := rod.Try(func() {
		cookies := b.MustGetCookies()
		for _, v := range cookies {
			var cookie http.Cookie
			cookie.Name = v.Name
			cookie.Value = v.Value
			cookie.Path = v.Path
			cookie.Domain = v.Domain
			domainMap[v.Domain] = append(domainMap[v.Domain], &cookie)
		}
		for _, cookie := range domainMap {
			clientURL, _ := url.Parse(BaseURL)
			c.Jar.SetCookies(clientURL, cookie)
		}
	})
	return c, e
}

func BrowserToClientYunnan(b *rod.Browser, BaseURL string) (*http.Client, error) {
	domainMap := map[string][]*http.Cookie{}
	c := lxhttp.NewHttpClient()
	e := rod.Try(func() {
		cookies := b.MustGetCookies()
		for _, v := range cookies {
			var cookie http.Cookie
			cookie.Name = v.Name
			cookie.Value = v.Value
			cookie.Path = v.Path
			cookie.Domain = v.Domain
			domainMap[v.Domain] = append(domainMap[v.Domain], &cookie)
		}
		for _, cookie := range domainMap {
			clientURL, _ := url.Parse(BaseURL)
			c.Jar.SetCookies(clientURL, cookie)
		}
		u, auth := GetLocalProxy("yunnan")
		uu, _ := url.Parse(u)
		c.Transport = &http.Transport{Proxy: http.ProxyURL(uu), ProxyConnectHeader: http.Header{
			"Proxy-Authorization": []string{"Basic " + base64.StdEncoding.EncodeToString([]byte(auth))},
		}}
	})
	return c, e
}

func BrowserToClientByProxy(b *rod.Browser, BaseURL string) (*http.Client, error) {
	area := ""
	{
		u, _ := url.Parse(BaseURL)
		area = strings.Split(u.Host, ".")[1]
	}
	if area == "" {
		return lxhttp.NewHttpClient(), taxerr.TimeOut
	}
	domainMap := map[string][]*http.Cookie{}
	c := lxhttp.NewHttpClient()
	proxy, auth := GetLocalProxy(area)
	uu, _ := url.Parse(proxy)
	tr := &http.Transport{Proxy: http.ProxyURL(uu)}
	if auth != "" {
		tr.ProxyConnectHeader = http.Header{
			"Proxy-Authorization": []string{"Basic " + base64.StdEncoding.EncodeToString([]byte(auth))},
		}
	}
	c.Transport = tr
	e := rod.Try(func() {
		cookies := b.MustGetCookies()
		for _, v := range cookies {
			var cookie http.Cookie
			cookie.Name = v.Name
			cookie.Value = v.Value
			cookie.Path = v.Path
			cookie.Domain = v.Domain
			domainMap[v.Domain] = append(domainMap[v.Domain], &cookie)
		}
		for _, cookie := range domainMap {
			clientURL, _ := url.Parse(BaseURL)
			c.Jar.SetCookies(clientURL, cookie)
		}
	})
	return c, e
}

func (lxrod *Lxrod) NewByHjj(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
	_ = rod.Try(func() {
		_ = lxrod.CloseBrowser()
	})
	lxrod.Launcher = launcher.New()
	lxrod.Launcher.Set("window-size", "1600,900").
		Set("no-sandbox").
		Set("ignore-certificate-errors").
		Set("ignore-certificate-errors-spki-list").
		Set("ignore-ssl-errors").
		Set("disable-features", "CalculateNativeWinOcclusion").
		Headless(lxrod.Headless)
	//lxrod.Launcher.UserDataDir("user-data")
	lxrod.Launcher.Flags["disable-blink-features"] = []string{"AutomationControlled"}
	u, err := lxrod.Launcher.Launch()
	if err != nil {

		err = taxerr.New("调用浏览器失败,请稍后重试！")
		return lxrod.Browser, p, err
	}
	err = rod.Try(func() {
		lxrod.Browser = rod.New().ControlURL(u).MustConnect().Context(ctx)
		utils.Sleep(1)
		lxrod.Browser.MustSetCookies()
	})
	if err != nil {
		return nil, nil, taxerr.NewWebStuckTitle(true)
	}
	lxrod.Browser.NoDefaultDevice()
	p = stealth.MustPage(lxrod.Browser)
	if lxrod.MonitorDialog {
		//为新打开的页面添加一个dialog监控
		DialogWatch(ctx, p)
		go lxrod.Browser.EachEvent(func(e *proto.TargetTargetCreated) {
			defer func() {
				if r := recover(); r != nil {

				}
			}()
			if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
				return
			}
			page := lxrod.Browser.MustPageFromTargetID(e.TargetInfo.TargetID)
			DialogWatch(ctx, page)
		})()
	}
	p = p.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
	return lxrod.Browser, p, err
}

// 新建浏览器对象
func (lxrod *Lxrod) NewBeijing(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
	rod.Try(func() {
		lxrod.CloseBrowser()
		os.RemoveAll("tmp/")
	})

	lxrod.Launcher = launcher.NewUserMode()
	u, err := lxrod.Launcher.
		// New().
		Leakless(true).
		UserDataDir("tmp/t").
		Set("disable-default-apps").
		Set("no-first-run").
		//Set("disable-plugins").
		Set("disable-popup-blocking").
		Set("disable-features", "CalculateNativeWinOcclusion").
		Headless(lxrod.Headless).
		Launch()
	if err != nil {

		return nil, nil, taxerr.NewUser("浏览器创建失败请稍后重试1")
	}

	utils.Sleep(3)

	err = rod.Try(func() {
		b = rod.New().ControlURL(u).Timeout(time.Second * 60).MustConnect().Context(ctx).NoDefaultDevice()
	})
	if err != nil {

		return nil, nil, taxerr.NewUser("浏览器创建失败请稍后重试2")
	}

	b.MustIncognito()
	p = b.MustPage("")
	lxrod.Browser = b
	go b.EachEvent(func(e *proto.TargetTargetCreated) {
		defer func() {
			if r := recover(); r != nil {

			}
		}()
		if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
			return
		}
		page := b.MustPageFromTargetID(e.TargetInfo.TargetID)
		page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
	})()
	return b, p, err
}

func (lxrod *Lxrod) NewHuBei(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
	rod.Try(func() {
		lxrod.CloseBrowser()
	})
	l := launcher.
		New().
		Set("window-size", "1600,900").
		Leakless(true).
		Set("disable-features", "CalculateNativeWinOcclusion").
		Headless(false)
	lxrod.Launcher = l
	//lxrod.Launcher.UserDataDir("user-data")
	l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
	//if viper.GetString("env") == string(variable.Development) {
	//	l.Leakless(false) //开发环境不使用用leakless
	//}
	u := l.MustLaunch()

	b = rod.New().ControlURL(u).MustConnect().NoDefaultDevice()
	p = stealth.MustPage(b)
	lxrod.Browser = b
	go b.EachEvent(func(e *proto.TargetTargetCreated) {
		defer func() {
			if r := recover(); r != nil {

			}
		}()
		if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
			return
		}
		page := b.MustPageFromTargetID(e.TargetInfo.TargetID)

		_, err := page.EvalOnNewDocument(stealth.JS)
		if err != nil {
			return
		}
		page.MustEvalOnNewDocument(stealth.JS)
		page.MustSetUserAgent(nil)
		utils.E(proto.RuntimeRunIfWaitingForDebugger{}.Call(page))
		page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
	})()
	utils.E(proto.TargetSetAutoAttach{
		AutoAttach:             true,
		WaitForDebuggerOnStart: true,
		Flatten:                true,
	}.Call(b))
	return b, p, err
}
func (lxrod *Lxrod) NewNoParam() (b *rod.Browser, p *rod.Page, err error) {
	rod.Try(func() {
		lxrod.CloseBrowser()
	})
	l := launcher.
		New().
		Set("window-size", "1600,900").
		Leakless(true).
		Set("disable-features", "CalculateNativeWinOcclusion").
		Headless(false)
	lxrod.Launcher = l
	//lxrod.Launcher.UserDataDir("user-data")
	l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
	//if viper.GetString("env") == string(variable.Development) {
	//	l.Leakless(false) //开发环境不使用用leakless
	//}
	u := l.MustLaunch()

	b = rod.New().ControlURL(u).MustConnect().NoDefaultDevice()
	p = stealth.MustPage(b)
	lxrod.Browser = b
	go b.EachEvent(func(e *proto.TargetTargetCreated) {
		defer func() {
			if r := recover(); r != nil {

			}
		}()
		if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
			return
		}
		page := b.MustPageFromTargetID(e.TargetInfo.TargetID)

		_, err := page.EvalOnNewDocument(stealth.JS)
		if err != nil {
			return
		}
		page.MustEvalOnNewDocument(stealth.JS)
		page.MustSetUserAgent(nil)
		utils.E(proto.RuntimeRunIfWaitingForDebugger{}.Call(page))
		page.MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
	})()
	utils.E(proto.TargetSetAutoAttach{
		AutoAttach:             true,
		WaitForDebuggerOnStart: true,
		Flatten:                true,
	}.Call(b))
	return b, p, err
}

// 最简单的浏览器创建
func (lxrod *Lxrod) NewLowBrowser(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
	rod.Try(func() {
		if lxrod.Browser != nil {
			lxrod.CloseBrowser()
			utils.Sleep(5)
		}
	})
	l := launcher.New().
		Headless(false).
		Set("high-dpi-support", "1").
		Set("disable-features", "CalculateNativeWinOcclusion").
		Set("force-device-scale-factor", "1")
	l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
	lxrod.Launcher = l
	//lxrod.Launcher.UserDataDir("user-data")
	//if lxrod.Area == "hebei" {
	//	lxrod.Launcher.UserDataDir("user-data")
	//}
	if lxrod.UseProxy {
		lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area))
		lxrod.Launcher.Proxy(lxrod.Proxy)
	}
	wsURL, err := l.Launch()

	lxrod.WsURL = wsURL
	if err != nil {
		return nil, nil, taxerr.NewWebStuckTitle(true)
	}
	b = rod.New().ControlURL(wsURL).Context(ctx).MustConnect().MustIgnoreCertErrors(true)
	utils.Sleep(1)
	b = b.MustSetCookies()

	if lxrod.UseProxy && lxrod.ProxyAuth != "" {
		auths := strings.Split(lxrod.ProxyAuth, ":")
		go b.HandleAuth(auths[0], auths[1])()
	}
	p = b.MustPage().MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)

	if lxrod.MonitorDialog && lxrod.NoEachEventForCreated {
		//为新打开的页面添加一个dialog监控
		DialogWatch(ctx, p)
		go b.EachEvent(func(e *proto.TargetTargetCreated) {
			defer func() {
				if r := recover(); r != nil {

				}
			}()
			if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
				return
			}
			page := b.MustPageFromTargetID(e.TargetInfo.TargetID)
			DialogWatch(ctx, page)
		})()
	}
	lxrod.Browser = b
	return b, p, nil
}

// NewBrowserBank360 打开 360 急速浏览器。适用于既要 ocx 密码输入又要 chrome 采集的银行任务，
// 如承德银行。运行前需要先安装 360 急速浏览器，然后将 360 急速浏览器的安装目录添加到环境变量中。
// 对于银行采集服务器，这个目录一般是：
//
//	"C:\\Users\\taxrobot\\Desktop\\360Chrome1\\"
func (lxrod *Lxrod) NewBrowserBank360(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
	rod.Try(func() {
		lxrod.CloseBrowser()
	})

	bin, err := exec.LookPath("360chromeX.exe")
	if err != nil {
		return nil, nil, taxerr.NewUser("请先安装360极速浏览器(" + err.Error() + ")")
	}

	l := launcher.New().
		Headless(false).
		Bin(bin).
		//Bin("C:\\Program Files (x86)\\税局小助手\\360Chrome\\360chromeX.exe").
		Set("high-dpi-support", "1").
		Set("disable-features", "CalculateNativeWinOcclusion").
		Set("force-device-scale-factor", "1")
	l.Flags["disable-blink-features"] = []string{"AutomationControlled"}

	lxrod.Launcher = l
	wsURL, err := l.Launch()
	lxrod.WsURL = wsURL
	if err != nil {

		return nil, nil, taxerr.NewWebStuckTitle(true)
	}

	b = rod.New().ControlURL(wsURL).Context(ctx).MustConnect()
	p = b.MustPage().MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)

	if lxrod.MonitorDialog {
		//为新打开的页面添加一个dialog监控
		DialogWatch(ctx, p)
		go b.EachEvent(func(e *proto.TargetTargetCreated) {
			defer func() {
				if r := recover(); r != nil {

				}
			}()
			if e.TargetInfo.Type != proto.TargetTargetInfoTypePage {
				return
			}
			page := b.MustPageFromTargetID(e.TargetInfo.TargetID)
			DialogWatch(ctx, page)
		})()
	}
	lxrod.Browser = b

	return b, p, nil
}

// 最简单的浏览器创建2
func (lxrod *Lxrod) NewLowBrowser2(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
	rod.Try(func() {
		lxrod.CloseBrowser()
	})
	l := launcher.New().
		Headless(false).
		Set("high-dpi-support", "1").
		Set("disable-features", "CalculateNativeWinOcclusion").
		Set("force-device-scale-factor", "1")
	l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
	lxrod.Launcher = l
	//lxrod.Launcher.UserDataDir("user-data")
	wsURL, err := l.Launch()
	if err != nil {

		return nil, nil, taxerr.NewWebStuckTitle(true)
	}
	b = rod.New().ControlURL(wsURL).Context(ctx).MustConnect()
	p = b.MustPage().MustSetWindow(0, 0, 1600, 900).MustSetViewport(1600, 900, 1, false)
	lxrod.Browser = b
	if lxrod.MonitorDialog {
		DialogWatch(ctx, p) //为新打开的页面添加一个dialog监控
	}
	if lxrod.UseProxy {
		lxrod.Proxy, lxrod.ProxyAuth = GetLocalProxy(string(lxrod.Area))
		lxrod.Launcher.Proxy(lxrod.Proxy)
	}
	return b, p, nil
}

// 自定义鼠标操作 方便升降版本
type Mouse struct {
	Mouse *rod.Mouse
}

func (m *Mouse) MustMove(x, y float64) *Mouse {
	m.Mouse.MustMoveTo(x, y)
	return m
}

func (m *Mouse) MustDown(button proto.InputMouseButton) *Mouse {
	m.Mouse.MustDown(button)
	return m
}

func (m *Mouse) MustUp(button proto.InputMouseButton) *Mouse {
	m.Mouse.MustUp(button)
	return m
}

func (m *Mouse) MustClick(button proto.InputMouseButton) *Mouse {
	m.Mouse.MustClick(button)
	return m
}

func ShenzhenProxy() string {
	// 获取私密代理IP API
	api := "https://dps.kdlapi.com/api/getdps"

	// 请求参数
	params := url.Values{}
	params.Set("secret_id", "odr5kxfzzky69wbtuhzh")
	params.Set("signature", "qwndesfg2ouix111a8rfzyixou7q9nr3")
	params.Set("num", strconv.Itoa(1)) // 提取数量

	// 构建完整的URL，包括参数
	fullURL := api + "?" + params.Encode()

	// 发送GET请求
	response, err := http.Get(fullURL)
	if err != nil {
		fmt.Println("Error:", err)
		return ""
	}
	defer response.Body.Close()

	// 读取响应内容
	body, err := io.ReadAll(response.Body)
	if err != nil {
		fmt.Println("Error reading response body:", err)
		return ""
	}

	// 输出响应结果
	return "http://" + string(body)
}

// 备用
func (lxrod *Lxrod) BeijingNew(ctx context.Context) (b *rod.Browser, p *rod.Page, err error) {
	_ = rod.Try(func() {
		lxrod.CloseBrowser()
	})
	l := launcher.New().Set("window-size", "1600,900").
		Delete("enable-automation").
		Leakless(true).
		Headless(false).Set("disable-features", "CalculateNativeWinOcclusion")
	l.Flags["disable-blink-features"] = []string{"AutomationControlled"}
	u := l.MustLaunch()
	b = rod.New().ControlURL(u).MustConnect()
	p = b.MustPage("")
	lxrod.Browser = b
	return b, p, nil
}

// GetLocalProxy 获取所有地区代理 部分地区是使用的我们自己的代理池
func GetLocalProxy(Area string) (string, string) {
	// 都换成5879
	//if Area == "xizang" /*|| Area == "yunnan"*/ || Area == "hebei" || Area == "liaoning" || Area == "chongqing" || Area == "sichuan" {
	//	return `http://8.141.85.129:5879`, "lxuser:Aa123456"
	//}
	if Area == "yunnan" {
		return "http://106.58.178.172:27237", "13280888700:nPDZ0RYX"
	}
	if Area == "shenzhen" {
		return ShenzhenProxy(), "d2879234360:ikdnhzbk"
	}
	return `http://8.141.85.129:5879`, "Ixuser:Aa123456"
}
