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",
		},
	}
	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"]
	}
	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
	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()
	// 判断当前是否是邮箱注册
	// _, err := page.Element(`input[name="email"]`)
	// if err != nil {
	switchButton := page.Timeout(5 * time.Second).MustElement(`button.css-146c3p1.r-bcqeeo.r-qvutc0.r-37j5jr.r-1ff274t.r-a023e6.r-rjixqe.r-16dba41`)
	switchButton.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`)
	// 月份
	dateSelects[0].WaitVisible()
	dateSelects[0].MustSelect(strconv.Itoa(dateParams.Month))
	// 日期
	dateSelects[1].WaitVisible()
	dateSelects[1].MustSelect(strconv.Itoa(dateParams.Day))
	// 年份
	dateSelects[2].WaitVisible()
	dateSelects[2].MustSelect(strconv.Itoa(dateParams.Year))

	// 点击下一步
	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, "")
	}
	//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()
	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,
	})
	// 删除浏览器
	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"]
}
