package login

import (
	"context"
	"crypto/tls"
	"fmt"
	"net/http"
	"net/url"
	"strings"
	"time"

	"git.listensoft.net/tool/jspkit/common"
	"git.listensoft.net/tool/jspkit/common/lxhttp"
	"git.listensoft.net/tool/jspkit/common/models"
	"git.listensoft.net/tool/jspkit/logger"
	"git.listensoft.net/tool/jspkit/taxerr"
	"github.com/go-rod/rod"
	"github.com/go-rod/rod/lib/proto"
	"github.com/go-rod/rod/lib/utils"
	"github.com/tidwall/gjson"
)

// MakeLoginData 生成登录信息
func MakeLoginData(ctx context.Context, info models.CompanyInfo) (jsonData map[string]any) {
	loginMethod := "QRCODE"
	TaxNo := info.TaxNo
	if info.Dlfs == "代理登录" {
		loginMethod = "MOBILE"
	}
	website := "etax"
	if ctxValue := ctx.Value("website"); ctxValue != nil {
		if websiteStr, ok := ctxValue.(string); ok {
			website = websiteStr
		}
	}
	// 拆分登陆方式
	switch info.Area {
	case "hubei", "guangdong", "zhejiang":
		if info.Dlfs == "新版登录" {
			loginMethod = "ACCOUNT"
		}
		if info.Dlfs == "代理登录" && (info.Area == "guangdong" || info.Area == "zhejiang") {
			loginMethod = "ACCOUNT"
		}
	default:
		if info.Dlfs == "新版登录" {
			loginMethod = "QRCODE"
		}
	}
	changeCreditCode := ""
	loginType := "QIYE"
	if info.Dlfs == "代理登录" {
		changeCreditCode = info.TaxNo
		info.TaxNo = info.IdNo
		loginType = "DAILI"
		TaxNo = info.IdNo
	}
	jsonData = map[string]any{
		"userInfo": map[string]string{
			"ComName":          info.ComName,
			"Name":             info.Area + ".pro",
			"CreditCode":       TaxNo,
			"Account":          info.Tel,
			"Password":         info.Zzrmm,
			"dailiCreditCode":  "",
			"changeCreditCode": changeCreditCode,
		},
		"areaName":    info.Area,
		"loginMethod": loginMethod,
		"loginType":   loginType,
		"website":     website,
		"source":      "taxRobot",
		//"proxies": proxies,
	}
	return
}

// PostLoin 登录函数
func PostLoin(jsonR []byte, headder map[string]string, info models.CompanyInfo) (response []byte, err error) {
	f := 0
	//begin:
	//logger.Info(string(jsonR))
	c := lxhttp.NewHttpClient() //http://dppt.jsptax.com:81
	if info.Dlfs == "代理登录" {
		tr := &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, //忽略证书校验
		}
		c = &http.Client{
			Timeout:   time.Duration(400 * time.Second),
			Transport: tr,
		}
	}
	response, err = lxhttp.PostByteReader(c, ETaxServe+"/api/login", jsonR, headder, nil)
	if err != nil {
		logger.Error(err.Error())
		if f < 6 {
			utils.Sleep(5)
			f++
			//goto begin
		}
		return response, taxerr.NewWebStuckTitle(info.Cscsts)
	}
	if strings.Contains(string(response), "Sorry, the page you are looking for is currently unavailable") || strings.Contains(string(response), "二维码已失效") ||
		strings.Contains(string(response), "ReadTimeoutError") || strings.Contains(string(response), "ProtocolError") {
		if f <= 3 {
			f++
			//goto begin
		}
		return nil, taxerr.New("新版税局登陆超时")
	}
	// 登录繁忙等30s
	if strings.Contains(string(response), "税局服务繁忙，请5分钟后重试") {
		utils.Sleep(30)
		if f <= 3 {
			f++
			//goto begin
		}
	}

	if (gjson.GetBytes(response, "msg").String() != "" && gjson.GetBytes(response, "msg").String() != "[登录成功~]") ||
		(gjson.GetBytes(response, "status").String() != "ok") {
		Str := gjson.GetBytes(response, "error").String()
		if Str == "" {
			// {"status":"false","msg":"[切换身份失败, 不存在用户91370203MA3RCTAU0X~]"}
			// {"status":"false","msg":"[切换身份失败, 连续认证错误次数过多，您的账号已被锁定。建议您直接使用“忘记密码”修改密码后重新登录或等待次日零时自动解锁。~]"}
			Str = gjson.GetBytes(response, "msg").String()
		}
		if Str == "" {
			Str = "新版税局登陆超时2"
		}
		if strings.Contains(Str, `请调用发送验证码`) && info.Dlfs == "新版登录" {
			common.DeleteTpassCookie(info)
		}
		if strings.Contains(Str, `请调用发送验证码`) && info.Dlfs == "代理登录" {
			err = taxerr.NewUserV3(`代理登录已掉线`, "请保证设备或app在线后重新发起任务")
			return
		}
		// 税局登录失败['bool' object is not subscriptable] 这个错误直接返回连续认证错误次数过多
		if strings.Contains(Str, `税局登录失败['bool' object is not subscriptable]`) {
			err = taxerr.FormatLoginError("税局登录失败[连续认证错误次数过多，您的账号已被锁定。建议您直接使用“忘记密码”修改密码后重新登录或等待次日零时自动解锁。]")
			return
		}
		err = taxerr.FormatLoginError(Str)
		return
	}
	return
}

func RsCookie(url string) (ck []*http.Cookie, uri string) {
	return nil, url
	if lxhttp.NeedRsvmp(url) {
		ck, _ = lxhttp.Rsvmp(url)
		return ck, url
	}
	return nil, url
}

// RefreshCookieBase 刷新增值税cookie和财报cookie
func refreshCookieBase(client *http.Client, area, BaseIndex, api, new_key16, token string) {
	f := 0
begin:
	headers := map[string]string{
		"Accept-Encoding": "gzip, deflate, br, zstd",
		"Accept-Language": "zh-CN,zh;q=0.9",
		"Accept":          "application/json, text/plain, */*",
		"Content-Type":    "application/json",
		"deviceIdentyNo":  "740qhjjFG7xSNQoCFtSHA7AMzikTKeJ5",
		"User-Agent":      "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
		"X-TICKET-ID":     "null",
		"X-NATURE-IP":     "",
		"X-SM4-INFO":      "0",
		"X-TEMP-INFO":     "null",
		"hUid":            "",
		"X-APP-CLIENTID":  "",
		"X-LANG-ID":       "null",
		"Authorization":   token,
	}
	logger.Info("埋点1")
	rst := lxhttp.Get_etax_clientId_redirectUri(client, api, RsCookie)
	logger.Info("埋点2")
	if rst == nil {
		return
	}
	logger.Info("埋点3")
	client_id := rst["client_id"].(string)
	redirect_uri := rst["redirect_uri"].(string)
	redirect_uri, _ = url.QueryUnescape(redirect_uri)
	code := lxhttp.VerifyLogin(client, area, BaseIndex, client_id, redirect_uri, new_key16, headers, RsCookie)
	logger.Info("埋点4")
	queryParams := url.Values{}
	queryParams.Add("code", code)
	if !strings.Contains(api, "invoice-query/invoice-query") {
		queryParams.Add("state", rst["state"].(string))
	}
	queryParams.Add("response_type", rst["response_type"].(string))
	hasQueryParams := strings.Contains(redirect_uri, "?")
	var finalRedirectURI string
	if hasQueryParams {
		finalRedirectURI = fmt.Sprintf("%s&%s", redirect_uri, queryParams.Encode())
	} else {
		finalRedirectURI = fmt.Sprintf("%s?%s", redirect_uri, queryParams.Encode())
	}
	fmt.Println("刷新cookie-uri:", finalRedirectURI)
	res, err := lxhttp.GET(client, finalRedirectURI, map[string]string{}, headers)
	if err != nil {
		_ = rod.Try(func() {
			logger.Info("finalRedirectURI失败:" + string(res))
			logger.Info("finalRedirectURI失败:" + err.Error())
		})
		if strings.Contains(BaseIndex, "neimeng") && f < 7 {
			f++
			goto begin
		}
	}
	fmt.Println(string(res))
	return
}

// RefreshCookieForAfterLogin RefreshCookie 主函数-对外开放 可以刷新两个cookie
func RefreshCookieForAfterLogin(cookies map[string]string, area, BaseIndex, new_key16, token string, cwbb bool) (client *http.Client) {
	client = lxhttp.NewHttpClientForNoRedirects("", "")
	var cks []*http.Cookie
	for k, v := range cookies {
		cks = append(cks, &http.Cookie{
			Name:  k,
			Value: v,
		})
	}
	u, _ := url.Parse(BaseIndex)
	client.Jar.SetCookies(u, cks)
	uri := BaseIndex + `/szc/szzh/sbss/ssmx/public/v1/checkLoginState`
	if !cwbb {
		uri = BaseIndex + "/szc/szzh/sjswszzh/sy/redirect?pageName=zhgl"
	}
	err := rod.Try(func() {
		refreshCookieBase(client, area, BaseIndex, uri, new_key16, token)
	})
	if err != nil {
		logger.Info(err.Error())
		return nil
	}
	return client
}

// RefreshCookieForAfterLoginRod rod使用替代afterlogin
func RefreshCookieForAfterLoginRod(page *rod.Page, proxy, proxyAuth, area, BaseIndex string, cwbb bool) (client *http.Client, err error) {
	Tpassuri := fmt.Sprintf(`https://tpass.%s.chinatax.gov.cn:8443/#/identitySwitch/enterprise`, area)
	client = lxhttp.NewHttpClientForNoRedirects(proxy, proxyAuth)
	cookies := page.Browser().MustGetCookies()
	var cookiesArr []*http.Cookie
	for _, v := range cookies {
		var cookie http.Cookie
		cookie.Name = v.Name
		cookie.Value = v.Value
		cookie.Path = v.Path
		cookie.Domain = v.Domain
		cookiesArr = append(cookiesArr, &cookie)
	}
	u, _ := url.Parse(BaseIndex)
	client.Jar.SetCookies(u, cookiesArr)
	new_key16, token, err := GetTpassToken(page, Tpassuri)
	if err != nil {
		return
	}
	logger.Info("GetTpassToken完成")
	Api := BaseIndex + `/szc/szzh/sbss/ssmx/public/v1/checkLoginState`
	if !cwbb {
		Api = BaseIndex + "/szc/szzh/sjswszzh/sy/redirect?pageName=zhgl"
	}
	if area == "shanxi" {
		Api = `https://etax.shanxi.chinatax.gov.cn:8443/szc/szzh/sjswszzh/spHandler?cdlj=/szzh/szzh/`
	}
	err = rod.Try(func() {
		logger.Info("开始refreshCookieBase")
		refreshCookieBase(client, area, BaseIndex, Api, new_key16, token)
		logger.Info("结束refreshCookieBase")
	})
	if err != nil {
		logger.Info(err.Error())
	}
	return client, err
}

// RefreshCookieForAfterLogin RefreshCookie 主函数-对外开放 可以刷新两个cookie
func RefreshDppt(page *rod.Page, area string) {
	e := rod.Try(func() {
		BaseIndex := GetBaseUri(area)
		client := lxhttp.NewHttpClientForNoRedirects("", "")
		{
			var cks []*http.Cookie
			for _, v := range page.Browser().MustGetCookies() {
				cks = append(cks, &http.Cookie{
					Name:  v.Name,
					Value: v.Value,
				})
			}
			u, _ := url.Parse(strings.ReplaceAll(BaseIndex, "etax", "dppt"))
			client.Jar.SetCookies(u, cks)
			u, _ = url.Parse(BaseIndex)
			client.Jar.SetCookies(u, cks)
		}
		TpassUri := fmt.Sprintf(`https://tpass.%s.chinatax.gov.cn:8443/#/identitySwitch/enterprise`, area)
		new_key16, token, _ := GetTpassToken(page, TpassUri)
		if new_key16 == "" {
			return
		}
		uri := strings.ReplaceAll(GetBaseUri(area), "etax", "dppt") + "/szzhzz/spHandler?cdlj=third-menu/invoice-query/invoice-query"
		refreshCookieBase(client, area, BaseIndex, uri, new_key16, token)
		var rodCookies []*proto.NetworkCookieParam
		u, _ := url.Parse(BaseIndex)
		for _, v := range client.Jar.Cookies(u) {
			rodCookies = append(rodCookies,
				&proto.NetworkCookieParam{
					Name:   v.Name,
					Value:  v.Value,
					Domain: ".chinatax.gov.cn",
					Path:   "/",
				},
			)
		}
		logger.Info("xxxx4")
		_ = page.Browser().SetCookies(rodCookies)
	})
	if e != nil {
		logger.Info(e.Error())
	}
	return
}

func GetTpassToken(page *rod.Page, TpassUrl string) (string, string, error) {
	var new_key16, token string
	err := rod.Try(func() {
		home := page.MustInfo().URL
		logger.Info(home)
		cookies := page.Browser().MustGetCookies()
		Ck := map[string]string{}
		for _, cookie := range cookies {
			Ck[cookie.Name] = cookie.Value
		}
		// 避免进不去
		for range "..." {
			page.MustNavigate(TpassUrl)
			utils.Sleep(2) // 加校验 //span[text()="身份切换"]
			page.MustWaitLoad()
			if common.MustHasXV(page, `//span[text()="身份切换"]`) {
				break
			} else {
				utils.Sleep(1.5)
			}
		}
		if !common.MustHasXV(page, `//span[text()="身份切换"]`) {
			panic(taxerr.New("获取企业所得税超时,系统将于30分钟后重试(可在\"通用设置\"关闭)"))
		}
		_ = rod.Try(func() {
			new_key16 = page.MustEval(`()=>localStorage.getItem('new_key16')`).String()
		})
		_ = rod.Try(func() {
			token = page.MustEval(`()=>localStorage.getItem('token')`).String()
		})
		logger.Info("New_key16:" + new_key16)
		logger.Info("Token:" + token)
		page.Navigate(home)
	})
	if new_key16 == "" {
		err = taxerr.NewWebStuckTitle(common.InfoCscsts)
	}
	return new_key16, token, err
}
