package services

import (
	"encoding/json"
	"fmt"
	"go-account-register/libs"
	"go-account-register/models"
	"go-account-register/utils"
	"log"
	"strconv"
	"time"

	"github.com/go-rod/rod"
	"github.com/go-rod/rod/lib/proto"
)

type BitBrowserService struct {
}

var Browser libs.Browser
var Chrome libs.Chrome

type BitCookieParam struct {
	Domain         string  `json:"domain"`
	ExpirationDate float64 `json:"expirationDate"` // 必须为 number
	HttpOnly       bool    `json:"httpOnly"`
	Name           string  `json:"name"`
	Path           string  `json:"path"`
	Secure         bool    `json:"secure"`
	Session        bool    `json:"session"`
	StoreID        *string `json:"storeId"` // 允许 null，用指针
	Value          string  `json:"value"`
	SameSite       *string `json:"sameSite,omitempty"` // 可选字段，不填时省略
}

func (*BitBrowserService) CreateBrowser(proxy *models.Proxy, cookies []*proto.NetworkCookieParam) string {
	fingerprint := map[string]interface{}{
		"name":               fmt.Sprintf(`推特注册%s`, utils.RandString(10)),
		"proxyMethod":        2,
		"proxyType":          "noproxy",
		"host":               "",
		"port":               0,
		"proxyUserName":      "",
		"proxyPassword":      "",
		"randomFingerprint":  true,
		"syncTabs":           false,
		"syncCookies":        false,
		"browserFingerPrint": map[string]interface{}{
			// "coreVersion": "130",
			// "ostype":      "PC",
			// "os":          "Win32",
			// "osVersion":   "11,10",
			// "openWidth":                  1920,
			// "openHeight":                 1480,
			// "resolutionType":             "0",
			// "userAgent":                  "",    // ua，不填则自动生成
			// "isIpCreateTimeZone":         true,  // 基于IP生成对应的时区
			// "timeZone":                   "",    // 时区，isIpCreateTimeZone 为false时，参考附录中的时区列表
			// "timeZoneOffset":             0,     // isIpCreateTimeZone 为false时设置，时区偏移量
			// "webRTC":                     "3",   //webrtc 0 => 替换, 1 => 允许, 2 => 禁止, 3 => 隐私
			// "ignoreHttpsErrors":          false, // 忽略https证书错误，true, false
			// "position":                   "1",   //地理位置 0 => 询问, 1 => 允许, 2 => 禁止
			// "isIpCreatePosition":         true,  // 是否基于IP生成对应的地理位置
			// "lat":                        "",    // 纬度 isIpCreatePosition 为false时设置
			// "lng":                        "",    // 经度 isIpCreatePosition 为false时设置
			// "precisionData":              "",    //精度米 isIpCreatePosition 为false时设置
			// "isIpCreateLanguage":         true,  // 是否基于IP生成对应国家的浏览器语言
			// "languages":                  "",    // isIpCreateLanguage 为false时设置，值参考附录
			// "isIpCreateDisplayLanguage":  true,  // 是否基于IP生成对应国家的浏览器界面语言
			// "displayLanguages":           "",    // isIpCreateDisplayLanguage 为false时设置，默认为空，即跟随系统，值参考附录
			// "windowSizeLimit":            true,  // 分辨率类型为自定义，且ostype为PC时，此项有效，约束窗口最大尺寸不超过分辨率
			// "devicePixelRatio":           1,     // 显示缩放比例，默认1，填写时，建议 1, 1.5, 2, 2.5, 3
			// "fontType":                   "2",   // 字体生成类型 0 => 系统默认 | 2 => 随机
			// "canvas":                     "0",   //canvas 0随机｜1关闭
			// "webGL":                      "0",   //webGL图像，0随机｜1关闭
			// "webGLMeta":                  "0",   //webgl元数据 0自定义｜1关闭
			// "webGLManufacturer":          "",    // webGLMeta 自定义时，webGL厂商值，建议留空会自动生成
			// "webGLRender":                "",    // webGLMeta自定义时，webGL渲染值，建议留空自动生成
			// "audioContext":               "0",   // audioContext值，0随机｜1关闭
			// "mediaDevice":                "0",   // 媒体设备，0 随机 | 1 关闭
			// "speechVoices":               "0",   // Speech Voices，0随机｜1关闭
			// "hardwareConcurrency":        "4",   // 硬件并发数
			// "deviceMemory":               "8",   // 设备内存，4，8，不要传入大于8的值
			// "doNotTrack":                 "1",   // doNotTrack 1开启｜0关闭
			// "clientRectNoiseEnabled":     true,  // ClientRects true使用相匹配的值代替您真实的ClientRects | false每个浏览器使用当前电脑默认的ClientRects
			// "portScanProtect":            "0",   // 端口扫描保护 0开启｜1关闭，注意默认开启保护，组织所有本地127的ws链接，比如某些打印机之类的，如有连接本地服务需求，建议关闭，或者在 portWhiteList 中，填写对应端口，加入白名单
			// "portWhiteList":              "",    // 端口扫描保护开启时的白名单，逗号分隔
			// "deviceInfoEnabled":          true,  // 自定义设备信息，默认开启
			// "computerName":               "",    // deviceInfoEnabled 为true时设置，建议留空系统自动生成即可
			// "macAddr":                    "",    // deviceInfoEnabled 为true时设置，建议留空系统自动生成即可
			// "disableSslCipherSuitesFlag": false, // ssl是否禁用特性，默认不禁用，注意开启后自定义设置时，有可能会导致某些网站无法访问
			// "disableSslCipherSuites":     nil,   // ssl 禁用特性，序列化的ssl特性值，参考附录
			// "enablePlugins":              false, // 是否启用插件指纹
			// "plugins":                    "",    // enablePlugins为true时，序列化的插件值，插件指纹值参考附录
			// "launchArgs":                 "",    // 启动参数，如无痕模式打开，那么设置启动参数为 "--incognito", 多个启动参数用逗号分隔，如 "--incognito,--no-sandbox"
		},
	}
	if cookies != nil {
		var cookie []BitCookieParam
		for _, v := range cookies {
			cookie = append(cookie, BitCookieParam{
				Domain:         v.Domain,
				ExpirationDate: float64(v.Expires),
				HttpOnly:       v.HTTPOnly,
				Name:           v.Name,
				Path:           v.Path,
				Secure:         v.Secure,
				Session:        false,
				StoreID:        nil,
				Value:          v.Value,
				SameSite:       (*string)(&v.SameSite),
			})
		}
		data, _ := json.Marshal(cookie)
		fingerprint["cookie"] = data
	}
	if proxy != nil {
		var proxyHandle utils.ProxyHandle
		protocol, username, password, ip, port, err2 := proxyHandle.ParseProxy(proxy.Type + "://" + proxy.Proxy)
		if err2 == nil {
			fingerprint["proxyType"] = protocol
			fingerprint["host"] = ip
			fingerprint["port"] = port
			fingerprint["proxyUserName"] = username
			fingerprint["proxyPassword"] = password
		}

	}
	bitBrowserRequest := utils.NewBitBrowserRequest()
	jsonStr, _ := bitBrowserRequest.CreateBrowser(fingerprint)
	var rawData map[string]interface{}
	if err := json.Unmarshal([]byte(jsonStr.Body()), &rawData); err != nil {
		panic(err)
	}
	success := rawData["success"].(bool)
	if success {
		// 如果成功则将数据存入数据库
		data := rawData["data"].(map[string]interface{})
		id := data["id"].(string)
		browserInstanceService := InitBrowserInstanceService()
		var params = &models.BrowserInstance{
			BrowserId:   id,
			Fingerprint: data,
			UpdateTime:  time.Now().Unix(),
			CreateTime:  time.Now().Unix(),
		}
		if proxy != nil && proxy.Type != "" {
			params.Proxy = proxy.Type + "://" + proxy.Proxy
		}
		browserInstanceService.Create(params)
		return id
	}
	return ""
}

// 获取当前浏览器的pid
func (*BitBrowserService) GetPid(id string) int {
	// 获取当前
	bitBrowserRequest := utils.NewBitBrowserRequest()
	jsonStr, _ := bitBrowserRequest.GetPids([]string{id})
	var result struct {
		Data    map[string]int `json:"data"` // 动态键名 → 值
		Success bool           `json:"success"`
	}
	if err := json.Unmarshal([]byte(jsonStr.Body()), &result); err != nil {
		panic(err)
	}
	success := result.Success
	if success {
		data := result.Data
		if value, exists := data[id]; exists {
			return value
		} else {
			return 0
		}
	}
	return 0
}

// 打开浏览器
func (*BitBrowserService) OpenBrowser(browserId string) string {
	// 获取当前
	bitBrowserRequest := utils.NewBitBrowserRequest()
	data := map[string]interface{}{
		"id":    browserId,
		"queue": true,
	}
	jsonStr, _ := bitBrowserRequest.OpenBrowser(data)
	var rawData map[string]interface{}
	if err := json.Unmarshal([]byte(jsonStr.Body()), &rawData); err != nil {
		panic(err)
	}
	success := rawData["success"].(bool)
	if success {
		data := rawData["data"].(map[string]interface{})
		ws := data["ws"].(string)
		browserInstanceService := InitBrowserInstanceService()
		browserInstanceService.Update(browserId, &models.BrowserInstance{
			BrowserUrl: ws,
		})
		return ws
	}
	return ""
}

// 删除浏览器
func (*BitBrowserService) DeleteBrowser(browserId string) bool {
	bitBrowserRequest := utils.NewBitBrowserRequest()
	// 先关闭浏览器
	_, err := bitBrowserRequest.CloseBrowser(browserId)
	if err != nil {
		log.Println("关闭浏览器失败")
	}
	// 删除浏览器
	_, err2 := bitBrowserRequest.DeleteBrowser(browserId)
	log.Println("删除浏览器，", err2 == nil)
	return err2 == nil
}

func (bit *BitBrowserService) Register() *libs.ErrorInfo {
	// 随机获取代理
	proxyService := InitProxyService()
	proxy := proxyService.GetInfo()
	var browserId string
	// 创建新的浏览器
	if proxy != nil {
		browserId = bit.CreateBrowser(proxy, nil)
	} else {
		browserId = bit.CreateBrowser(nil, nil)
	}
	// 打开浏览器
	if browserId == "" {
		return libs.ErrorCode["BrowserCreationFailed"]
	}
	time.Sleep(10 * time.Second)
	ws := bit.OpenBrowser(browserId)
	if ws == "" {
		return libs.ErrorCode["BrowserCreationFailed"]
	}
	// 获取一个邮箱
	emailService := InitEmailService()

	emailInfo := emailService.GetEmailOne()
	log.Println("当前邮箱信息", emailInfo)
	obj := Browser.GetBitBrowser(ws)
	page := obj.Page
	err := rod.Try(func() {
		page.MustNavigate("https://x.com/i/flow/signup").MustWaitLoad()
		// 点击创建账号
		createAccount := page.Timeout(5 * time.Second).MustElement(`button.css-175oi2r.r-sdzlij.r-1phboty.r-rs99b7.r-lrvibr.r-ywje51.r-184id4b.r-13qz1uu.r-2yi16.r-1qi8awa.r-3pj75a.r-1loqt21.r-o7ynqc.r-6416eg.r-1ny4l3l`)
		createAccount.MustClick()
	})
	if err != nil {
		page.MustReload()
		time.Sleep(10 * time.Second)
		// 点击创建账号
		createAccount := page.Timeout(5 * time.Second).MustElement(`button.css-175oi2r.r-sdzlij.r-1phboty.r-rs99b7.r-lrvibr.r-ywje51.r-184id4b.r-13qz1uu.r-2yi16.r-1qi8awa.r-3pj75a.r-1loqt21.r-o7ynqc.r-6416eg.r-1ny4l3l`)
		createAccount.MustClick()
	}
	time.Sleep(5 * time.Second)
	// 判断当前是否是邮箱注册
	// _, err := page.Element(`input[name="email"]`)
	// if err != nil {
	switchButton, switchButtonErr := page.Timeout(5 * time.Second).Element(`button.css-146c3p1.r-bcqeeo.r-qvutc0.r-37j5jr.r-1ff274t.r-a023e6.r-rjixqe.r-16dba41`)
	if switchButtonErr == nil {
		switchButton.MustClick()
	}

	emailButtonQ, switchButtonErr := page.Timeout(5 * time.Second).Element(`button.css-146c3p1.r-bcqeeo.r-qvutc0.r-1tl8opc.r-1ff274t.r-a023e6.r-rjixqe.r-16dba41`)
	if switchButtonErr == nil {
		emailButtonQ.MustClick()
	}

	// }
	// 获取邮箱输入框
	inputEmail := page.Timeout(5 * time.Second).MustElement(`input[name="email"]`)
	inputEmail.MustFocus()
	inputEmail.MustInput(emailInfo.Email)
	// 获取名称输入框
	inputName := page.Timeout(5 * time.Second).MustElement(`input[name="name"]`)
	inputName.MustFocus()
	nameStr := emailInfo.Name
	if emailInfo.Name == "" {
		nameStr = utils.RandString(12)
	}
	inputName.MustInput(nameStr)
	// 随机生成生日
	dateParams := utils.RandDate(18, 80)
	dateSelects, _ := page.Timeout(5 * time.Second).Elements(`select.r-30o5oe.r-1niwhzg.r-17gur6a.r-1yadl64.r-18jsvk2.r-1loqt21.r-1inkyih.r-rjixqe.r-crgep1.r-1wzrnnt.r-1ny4l3l.r-t60dpp.r-xd6kpl.r-is05cd.r-ttdzmv`)
	log.Println(dateSelects)
	fmt.Println(strconv.Itoa(dateParams.Month))
	fmt.Println(strconv.Itoa(dateParams.Day))
	fmt.Println(strconv.Itoa(dateParams.Year))
	/// 月份
	dateSelects[0].WaitVisible()
	opts, _ := dateSelects[0].Elements("option")
	for i, opt := range opts {
		txt, _ := opt.Text()
		val, _ := opt.Attribute("value")
		log.Printf("option[%d] text=%s value=%s\n", i, txt, *val)
		if i != 0 && i == dateParams.Month {
			dateSelects[0].MustSelect(txt)
		}
	}
	// 年份
	dateSelects[2].WaitVisible()
	dateSelects[2].MustSelect(strconv.Itoa(dateParams.Year))
	// 日期
	dateSelects[1].WaitVisible()
	dateSelects[1].MustSelect(strconv.Itoa(dateParams.Day))
	// dateSelects[0].MustClick()
	// monthOption := dateSelects[0].MustElement(fmt.Sprintf(`option[value="%d"]`, dateParams.Month))
	// monthOption.MustClick()
	time.Sleep(2 * time.Second)
	// 点击下一步
	ocfSignupNextLink := page.Timeout(5 * time.Second).MustElement(`button[data-testid="ocfSignupNextLink"]`)
	ocfSignupNextLink.MustClick()
	// 判断是否需要验证码
	time.Sleep(4 * time.Second)
	_, err1 := page.Timeout(5 * time.Second).Element(`input[name="verfication_code"]`)
	if err1 != nil {
		// res := getApiResponse(page, "")
	}
	var codeInputVer *rod.Element = nil
	// 循环获取 验证码输入框
	for codeInputVer == nil {
		t, err1 := page.Timeout(5 * time.Second).Element(`input[name="verfication_code"]`)
		if err1 == nil {
			codeInputVer = t
		}
		time.Sleep(5 * time.Second)
	}
	//TODO 对接获取邮箱信息接口
	time.Sleep(10 * time.Second)
	codeValue := LoopGetEmailCode("pop.dragonsmail.com:993", emailInfo.Email, emailInfo.Password)
	if codeValue == "0" {
		emailService.Update(emailInfo.Email, models.Email{
			Status: 0,
		})
		return libs.ErrorCode["MailboxUnavailable"]
	}
	// 获取邮箱验证码
	log.Println("获取当前验证码", codeValue)
	codeInput1, _ := page.Timeout(5 * time.Second).Element(`input[name="verfication_code"]`)
	codeInput1.MustInput(codeValue)
	time.Sleep(2 * time.Second)
	// 点击下一步
	codeNextButton := page.Timeout(5 * time.Second).MustElement(`button.css-175oi2r.r-sdzlij.r-1phboty.r-rs99b7.r-lrvibr.r-19yznuf.r-64el8z.r-1fkl15p.r-1loqt21.r-o7ynqc.r-6416eg.r-1ny4l3l`)
	codeNextButton.MustClick()
	// // 点击验证按钮
	// verifyButton := page.Timeout(5 * time.Second).MustElement(`button[data-theme="home.verifyButton"]`)
	// verifyButton.MustClick()
	// 输入密码
	passwordInput, err2 := page.Timeout(5 * time.Second).Element(`input[name="password"]`)
	if err2 != nil {
		// res := getApiResponse(page, "")
	}

	passwordInput.MustInput(emailInfo.Password)
	time.Sleep(5 * time.Second)
	// 点击下一步
	loginButton := page.Timeout(5 * time.Second).MustElement(`button[data-testid="LoginForm_Login_Button"]`)
	loginButton.MustClick()
	time.Sleep(5 * time.Second)
	page.MustNavigate("https://x.com").MustWaitLoad()
	time.Sleep(10 * time.Second)
	// 获取cookie
	cookieArr := GetPageCookie(page, "https://x.com")
	// 创建用户
	twitterAccountService := InitTwitterAccountService()
	accountId := twitterAccountService.Create(&models.TwitterAccount{
		Name:        nameStr,
		Email:       emailInfo.Email,
		Password:    emailInfo.Password,
		Birthday:    strconv.Itoa(dateParams.Year) + "-" + strconv.Itoa(dateParams.Month) + "-" + strconv.Itoa(dateParams.Day),
		Cookies:     cookieArr,
		Status:      "注册成功",
		LoginStatus: "登录成功",
		Proxy: func() string {
			if proxy != nil && proxy.Type != "" {
				return proxy.Type + "://" + proxy.Proxy
			}
			return ""
		}(),
	})
	emailService.Update(emailInfo.Email, models.Email{
		UseStatus: 1,
	})
	// 设置fa2
	page.MustNavigate("https://x.com/settings/account/login_verification").MustWaitLoad()
	// 点击fa2按钮
	inputCheckbox := page.Timeout(5 * time.Second).MustElement(`input[aria-describedby="CHECKBOX_2_LABEL"]`)
	inputCheckbox.MustClick()
	// 等待2秒
	time.Sleep(2 * time.Second)
	// 设置密码
	inpurPassword, errPassword := page.Timeout(5 * time.Second).Element(`input[name="password"]`)
	if errPassword == nil {
		inpurPassword.MustInput(emailInfo.Password)
		// 点击确认
		faConfirm := page.Timeout(5 * time.Second).MustElement(`button[data-testid="LoginForm_Login_Button"]`)
		faConfirm.MustClick()
	}

	// 等待2秒
	time.Sleep(2 * time.Second)
	ActionListNextButton := page.Timeout(5 * time.Second).MustElement(`button[data-testid="ActionListNextButton"]`)
	ActionListNextButton.MustClick()
	// 点击无法扫描二维码
	queryCode := page.Timeout(5 * time.Second).MustElement("div.css-175oi2r.r-1awozwy.r-w7s2jr>div.css-175oi2r.r-95jzfe>div.css-146c3p1.r-bcqeeo.r-1ttztb7.r-qvutc0.r-37j5jr.r-a023e6.r-rjixqe.r-16dba41>button.css-1jxf684.r-bcqeeo.r-qvutc0.r-poiln3.r-fdjqy7")
	queryCode.MustClick()
	fa2Code := page.Timeout(5 * time.Second).MustElement(`div.css-146c3p1.r-bcqeeo.r-qvutc0.r-37j5jr.r-1blvdjr.r-vrz42v.r-b88u0q.r-x572qd.r-ywje51.r-1oqcu8e.r-q4m81j.r-13qz1uu`)
	fa2CodeText := fa2Code.MustText()
	log.Println("当前账号的二步验证码，", fa2CodeText)
	ocfShowCodeNextLink := page.Timeout(5 * time.Second).MustElement(`button[data-testid="ocfShowCodeNextLink"]`)
	ocfShowCodeNextLink.MustClick()
	codeText, _ := utils.GetFA2Code(fa2CodeText)
	ocfEnterTextTextInput := page.Timeout(5 * time.Second).MustElement(`input[data-testid="ocfEnterTextTextInput"]`)
	ocfEnterTextTextInput.MustInput(codeText)
	ocfEnterTextNextButton := page.Timeout(5 * time.Second).MustElement(`button[data-testid="ocfEnterTextNextButton"]`)
	ocfEnterTextNextButton.MustClick()
	OCF_CallToAction_Button, errOCF := page.Timeout(5 * time.Second).Element(`button[data-testid="OCF_CallToAction_Button"]`)
	if errOCF == nil {
		OCF_CallToAction_Button.MustClick()
	}
	if accountId != 0 {
		twitterAccountService.Update(accountId, &models.TwitterAccount{Fa2: fa2CodeText})
	}
	time.Sleep(2 * time.Second)
	page.MustNavigate("https://x.com/home").MustWaitLoad()
	// 删除浏览器
	// bit.DeleteBrowser(browserId)
	return libs.ErrorCode["RegisterSuccessful"]
}

// 获取指定页面的cookie列表
func GetPageCookie(page *rod.Page, url string) []*proto.NetworkCookieParam {
	cookieArr, _ := page.Cookies([]string{url})
	var cookies []*proto.NetworkCookieParam
	for _, cookie := range cookieArr {
		cookies = append(cookies, &proto.NetworkCookieParam{
			Name:     cookie.Name,
			Value:    cookie.Value,
			Domain:   cookie.Domain,
			Path:     cookie.Path,
			Expires:  cookie.Expires,  // 过期时间
			HTTPOnly: cookie.HTTPOnly, // 禁止 JS 访问
			Secure:   cookie.Secure,   // 仅 HTTPS 传输
		})
	}
	return cookies
}

// 循环获取3次验证码
func LoopGetEmailCode(server, email, password string) string {
	var emailImap utils.EmailImap
	for i := 0; i < 3; i++ {
		codeValue := emailImap.GetMailCode(server, email, password)
		if codeValue != "0" {
			return codeValue
		}
		time.Sleep(5 * time.Second)
	}
	return "0"
}

func (*BitBrowserService) AccountUnlock(id int64) *libs.ErrorInfo {
	return libs.ErrorCode["UnlockedSuccessfully"]
}
