package login

import (
	"context"
	"encoding/base64"
	"encoding/json"
	"fmt"
	"log"
	"strings"
	"time"

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

func CheckSessionAndLogin(ctx context.Context, p *rod.Page, BaseUri string, info models.CompanyInfo) (err error) {
	//return taxerr.NewUser("税局代理机构登录存在风险,预计6号恢复,请等待税局修复后使用")//12.6 09:20左右 确认完了
	if info.Dlfs == "代理登录" && info.IdNo == "" {
		return taxerr.DlTaxNoError
	}
	return AutoCheckSessionAndLogin(ctx, p, BaseUri, info)
}

func LoadCookie(sessionInfos models.SsoSession, p *rod.Page, BaseUri string, info models.CompanyInfo) (name string, err error) {
	err = rod.Try(func() {
		defer AddErr()
		p.Navigate("")
		_ = p.Timeout(common.ClickTimeOut).MustNavigate(areaURLmap[info.Area+".pro"]).StopLoading() // 此时必须得去tpass域名 要不然写入cookie后进不去发票
		p.MustSetCookies(sessionInfos.Cookies...)
		{
			p.MustEval(`() => localStorage.clear()`)
			utils.Sleep(1)
			// 设置 localStorage 在第二个页面中，逐条设置
			logger.Info("Setting localStorage in second browser...")
			for key, value := range sessionInfos.LocalStorage {
				if key == "logConfig" {
					continue
				}
				script := fmt.Sprintf(`() => localStorage.setItem('%s', '%s')`, key, value)
				_, err := p.Eval(script)
				if err != nil {
					log.Printf("Error setting localStorage %s=%s: %v", key, value, err)
				}
			}
		}
		utils.Sleep(1)
		if info.Area == "shaanxi" {
			//陕西地区必须带后面/才能登录上去
			p.Timeout(common.ClickTimeOut).MustNavigate(BaseUri + "/loginb/")
		} else {
			p.Timeout(common.ClickTimeOut).MustNavigate(BaseUri + "/loginb")
		}
		utils.Sleep(4)
		_ = rod.Try(func() {
			p.Timeout(common.LoadTimeout * 2).MustWaitStable()
			p.Timeout(common.LoadTimeout * 2).MustWaitDOMStable()
		})
		//p.MustStopLoading()
		logger.Info("加载完成")
		if info.Area == "hebei" && !common.MustHasXV(p, `//div[@class='leftMain']//div[contains(@class,'title')]`) {
			logger.Info("河北重新访问loginb")
			p.Timeout(common.ClickTimeOut).MustNavigate(`https://tpass.hebei.chinatax.gov.cn:8443/#/login?redirect_uri=https%3A%2F%2Fetax.hebei.chinatax.gov.cn%3A8443%2Fmhzx%2Fapi%2Fmh%2Ftpass%2Fcode&client_id=ap5bfdavp66a49979apa5848fpaa5353&response_type=code&state=8f8f3db7ecb948f08b1da177cda40854&client_pid=ap5bfdavp66a49979apa5848fpaa5353`)
			utils.Sleep(4)
			p.MustWaitStable()
			p.MustWaitDOMStable()
		}
		if common.MustHasXV(p, "//div[text()=' 关于电子税务局“新办智能开业”的通知 ']") {
			rod.Try(func() {
				p.Timeout(common.ClickTimeOut).MustSearch("//span[text()='我知道了']").MustClick()
				utils.Sleep(1)
				common.MustElementXV(p, "//span[text()='确认']").MustClick()
				utils.Sleep(40) //要转很久
				p.Timeout(common.ClickTimeOut).MustNavigate(BaseUri + "/loginb")
			})
		}
		if p.MustHasX(`//div[@class='leftMain']//div[contains(@class,'title')]`) {
			_ = p.Timeout(common.ClickTimeOut).MustElementX(`//div[@class='leftMain']//div[contains(@class,'title')]`).WaitStable(300 * time.Millisecond)
			if *p.Timeout(common.ClickTimeOut).MustElementX(`//div[@class='leftMain']//div[contains(@class,'title')]`).MustAttribute(`title`) == "" {
				logger.Info("公司名空刷新")
				p.Reload()
				utils.Sleep(4)
				p.MustWaitDOMStable()
			}
		}
		if common.MustHasXV(p, `//div[@class='leftMain']//div[contains(@class,'title')]`) {
			name = *common.WaitElementX(p, `//div[@class='leftMain']//div[contains(@class,'title')]`, 0.5).MustAttribute(`title`)
			if name == "" {
				err = taxerr.New("代理登录切换公司后异常公司名")
				return
			}
			return
		}
		DlSy := false //登录完是代理登录的首页
		if common.MustHasXV(p, `//a[@title="单户办理"]`) {
			common.MustElementX(p, `//a[@title="单户办理"]`).MustClick()
			DlSy = true
			utils.Sleep(3)
		}
		if !strings.Contains(p.MustInfo().URL, "tpass") {
			panic(taxerr.New("cookie失效"))
		}
		if !p.MustHasR(`[class="s_Breadcrumb"]`, "企业办税") {
			panic(taxerr.New("cookie失效"))
		}
		if !DlSy {
			r := p.MustWaitRequestIdle()
			p.Timeout(common.ClickTimeOut).MustSearch("返回").MustClick()
			r()
		} else {
			//这里需要手动切换到首页
			common.MustInputX(p, `//input[@placeholder="请输入统一社会信用代码"]`, info.TaxNo)
			common.MustElementX(p, `//span[text()="查询"]`).MustClick()
			utils.Sleep(2)
			tbody := common.MustElementsX(p, `//div[@class="el-table__body-wrapper is-scrolling-none"]//table//tr`)
			if len(tbody) == 0 {
				common.MustInputX(p, `//input[@placeholder="请输入统一社会信用代码"]`, "")
				p.Timeout(common.ClickTimeOut).MustElementX(`//input[@placeholder="请输入纳税人名称"]`).MustInput(info.ComName)
				common.MustElementX(p, `//span[text()="查询"]`).MustClick()
				utils.Sleep(2)
				tbody = common.MustElementsX(p, `//div[@class="el-table__body-wrapper is-scrolling-none"]//table//tr`)
				if len(tbody) == 0 {
					panic(taxerr.NewUserV3("未在当前账号下["+info.Zzridno+"]找到该企业", "请检查手机号与企业的关联关系"))
				}
				panic(taxerr.NewUserV3("该公司账号跟公司名称不匹配", "请检查后重新发起"))
			} else if len(tbody) == 1 {
				common.MustElementX(p, `//span[text()='进入']`).MustClick()
				if common.MustHasXV(p, `//span[text()="身份切换"]/../../..//span[contains(text(),"确定")]`) {
					common.MustElementX(p, `//span[text()="身份切换"]/../../..//span[contains(text(),"确定")]`).MustClick()
					time.Sleep(5 * time.Second)
				}
			} else {
				panic(taxerr.NewSystemV3("未在当前税号下["+info.TaxNo+"]找到多家企业", "请联系运维处理"))
			}
		}
		utils.Sleep(2)
		p.MustWaitDOMStable()
		name = *common.WaitElementX(p, `//div[@class='leftMain']//div[contains(@class,'title')]`, 0.5).MustAttribute(`title`)
	})
	// 这是panic的失效
	if err != nil {
		rod.Try(func() {
			patjh := common.GeneratePath("png")
			p.MustScreenshot(patjh)
			logger.Info("代理登录切换公司后异常公司名或判定为失效截图:" + patjh)
		})
		logger.Info(err.Error())
		return "", err
	}
	if (err != nil) && name == "" {
		logger.Info("cookie失效,当前url:" + p.MustInfo().URL)
		return "", taxerr.NewSystemV3("税局加载异常", "系统将于30分钟后重试")
	}
	return
}

func LoadCookieFast(sessionInfos models.SsoSession, p *rod.Page, BaseUri string, info models.CompanyInfo) (name string, err error) {
	err = rod.Try(func() {
		defer AddErr()
		p.Navigate("")
		p.Timeout(common.ClickTimeOut).MustNavigate(areaURLmap[info.Area+".pro"]).MustStopLoading() // 此时必须得去tpass域名 要不然写入cookie后进不去发票
		p.MustSetCookies(sessionInfos.Cookies...)
		{
			p.MustEval(`() => localStorage.clear()`)
			//utils.Sleep(1)
			// 设置 localStorage 在第二个页面中，逐条设置
			logger.Info("Setting localStorage in second browser...")
			for key, value := range sessionInfos.LocalStorage {
				if key == "logConfig" {
					continue
				}
				script := fmt.Sprintf(`() => localStorage.setItem('%s', '%s')`, key, value)
				_, err := p.Eval(script)
				if err != nil {
					log.Printf("Error setting localStorage %s=%s: %v", key, value, err)
				}
			}
		}
		utils.Sleep(0.5)
		if info.Area == "shaanxi" {
			//陕西地区必须带后面/才能登录上去
			p.Timeout(common.ClickTimeOut).MustNavigate(BaseUri + "/loginb/")
		} else {
			p.Timeout(common.ClickTimeOut).MustNavigate(BaseUri + "/loginb")
		}
		utils.Sleep(1)
		_ = rod.Try(func() {
			p.Timeout(2 * time.Second).MustWaitStable()
			p.Timeout(2 * time.Second).MustWaitDOMStable()
		})
		//p.MustStopLoading()
		logger.Info("加载完成")
		if info.Area == "hebei" && !common.MustHasXV(p, `//div[@class='leftMain']//div[contains(@class,'title')]`) {
			logger.Info("河北重新访问loginb")
			p.Timeout(common.ClickTimeOut).MustNavigate(`https://tpass.hebei.chinatax.gov.cn:8443/#/login?redirect_uri=https%3A%2F%2Fetax.hebei.chinatax.gov.cn%3A8443%2Fmhzx%2Fapi%2Fmh%2Ftpass%2Fcode&client_id=ap5bfdavp66a49979apa5848fpaa5353&response_type=code&state=8f8f3db7ecb948f08b1da177cda40854&client_pid=ap5bfdavp66a49979apa5848fpaa5353`)
			utils.Sleep(4)
			p.MustWaitStable()
			p.MustWaitDOMStable()
		}
		if common.MustHasXV(p, "//div[text()=' 关于电子税务局“新办智能开业”的通知 ']") {
			rod.Try(func() {
				p.Timeout(common.ClickTimeOut).MustSearch("//span[text()='我知道了']").MustClick()
				utils.Sleep(1)
				common.MustElementXV(p, "//span[text()='确认']").MustClick()
				utils.Sleep(40) //要转很久
				p.Timeout(common.ClickTimeOut).MustNavigate(BaseUri + "/loginb")
			})
		}
		if p.MustHasX(`//div[@class='leftMain']//div[contains(@class,'title')]`) {
			_ = p.Timeout(common.ClickTimeOut).MustElementX(`//div[@class='leftMain']//div[contains(@class,'title')]`).WaitStable(300 * time.Millisecond)
			if *p.Timeout(common.ClickTimeOut).MustElementX(`//div[@class='leftMain']//div[contains(@class,'title')]`).MustAttribute(`title`) == "" {
				logger.Info("公司名空刷新")
				p.Reload()
				utils.Sleep(4)
				p.MustWaitDOMStable()
			}
		}
		if common.MustHasXV(p, `//div[@class='leftMain']//div[contains(@class,'title')]`) {
			name = *common.WaitElementX(p, `//div[@class='leftMain']//div[contains(@class,'title')]`, 0.5).MustAttribute(`title`)
			if name == "" {
				err = taxerr.New("代理登录切换公司后异常公司名")
				return
			}
			return
		}
		DlSy := false //登录完是代理登录的首页
		if common.MustHasXV(p, `//a[@title="单户办理"]`) {
			common.MustElementX(p, `//a[@title="单户办理"]`).MustClick()
			DlSy = true
			utils.Sleep(3)
		}
		if !strings.Contains(p.MustInfo().URL, "tpass") {
			panic(taxerr.New("cookie失效"))
		}
		if !p.MustHasR(`[class="s_Breadcrumb"]`, "企业办税") {
			panic(taxerr.New("cookie失效"))
		}
		if !DlSy {
			r := p.MustWaitRequestIdle()
			p.Timeout(common.ClickTimeOut).MustSearch("返回").MustClick()
			r()
		} else {
			//这里需要手动切换到首页
			common.MustInputX(p, `//input[@placeholder="请输入统一社会信用代码"]`, info.TaxNo)
			common.MustElementX(p, `//span[text()="查询"]`).MustClick()
			utils.Sleep(2)
			tbody := common.MustElementsX(p, `//div[@class="el-table__body-wrapper is-scrolling-none"]//table//tr`)
			if len(tbody) == 0 {
				common.MustInputX(p, `//input[@placeholder="请输入统一社会信用代码"]`, "")
				p.Timeout(common.ClickTimeOut).MustElementX(`//input[@placeholder="请输入纳税人名称"]`).MustInput(info.ComName)
				common.MustElementX(p, `//span[text()="查询"]`).MustClick()
				utils.Sleep(2)
				tbody = common.MustElementsX(p, `//div[@class="el-table__body-wrapper is-scrolling-none"]//table//tr`)
				if len(tbody) == 0 {
					panic(taxerr.NewUserV3("未在当前账号下["+info.Zzridno+"]找到该企业", "请检查手机号与企业的关联关系"))
				}
				panic(taxerr.NewUserV3("该公司账号跟公司名称不匹配", "请检查后重新发起"))
			} else if len(tbody) == 1 {
				common.MustElementX(p, `//span[text()='进入']`).MustClick()
				if common.MustHasXV(p, `//span[text()="身份切换"]/../../..//span[contains(text(),"确定")]`) {
					common.MustElementX(p, `//span[text()="身份切换"]/../../..//span[contains(text(),"确定")]`).MustClick()
					time.Sleep(5 * time.Second)
				}
			} else {
				panic(taxerr.NewSystemV3("未在当前税号下["+info.TaxNo+"]找到多家企业", "请联系运维处理"))
			}
		}
		utils.Sleep(0.5)
		p.MustWaitDOMStable()
		name = *common.WaitElementX(p, `//div[@class='leftMain']//div[contains(@class,'title')]`, 0.5).MustAttribute(`title`)
		logger.Info(name)
	})
	// 这是panic的失效
	if err != nil {
		rod.Try(func() {
			patjh := common.GeneratePath("png")
			p.MustScreenshot(patjh)
			logger.Info("代理登录切换公司后异常公司名或判定为失效截图:" + patjh)
		})
		logger.Info(err.Error())
		return "", err
	}
	if (err != nil) && name == "" {
		logger.Info("cookie失效,当前url:" + p.MustInfo().URL)
		return "", taxerr.NewSystemV3("税局加载异常", "系统将于30分钟后重试")
	}
	if name == "" {
		logger.Info("公司名加载异常,当前url:" + p.MustInfo().URL)
		path := common.GeneratePath("png")
		p.MustScreenshot(path)
		logger.Info(path)
	}
	return
}

func AddErr() {
	if err := recover(); err != nil {
		e := err.(error)
		if _, ok := err.(*taxerr.UserErr); ok {
			err = taxerr.NewUser(e.Error() + "(代理登录失败)")
		}
		if _, ok := err.(*taxerr.SystemErr); ok {
			err = taxerr.New(e.Error() + "(代理登录失败)")
		}
		panic(err)
	}
}

func AutoCheckSessionAndLogin(ctx context.Context, p *rod.Page, BaseUri string, info models.CompanyInfo) (err error) {
	if info.Area == "hubei" && info.Dlfs == "代理登录" && len(info.Tel) != 11 {
		return taxerr.NewUserV3("湖北代理登录需要接受验证码", "请在登录信息中修改为手机号")
	}
	if info.Zzrmm == "" {
		return taxerr.PasswdEmpty
	}
	var LoginResponse []byte
	var Session models.SsoSession
	// 直接登录获取cookie
	{
		logger.Info("开始代理登陆获取cookie")
		LoginData := MakeLoginData(ctx, info)
		a, _ := json.Marshal(LoginData)
		logger.Info("代理登录加密前参数" + string(a))
		R := AesECBEncrypt(LoginData)
		headder := map[string]string{
			"User-Agent":   "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/125.0.0.0 Safari/537.36",
			"content-type": "application/json",
			"x-token":      XToken,
		}
		marshal, _ := json.Marshal(LoginData)
		logger.Info(fmt.Sprintf("PostLoin参数%s" + string(marshal)))
		LoginResponse, err = PostLoin(R, headder, info)
		logger.Info("代理登陆获取cookie成功")
		if err != nil {
			if info.Dlfs == "代理登录" {
				e := err.(error)
				if _, ok := err.(*taxerr.UserErr); ok {
					err = taxerr.NewUser(e.Error() + "(代理登录失败)")
				}
				if _, ok := err.(*taxerr.SystemErr); ok {
					err = taxerr.New(e.Error() + "(代理登录失败)")
				}
			}
			return err
		}
	}
	// 整理cookie
	{
		gdata := gjson.GetBytes(LoginResponse, "data")
		cookies := []*proto.NetworkCookieParam{}
		domain := ""
		gdata.Get("cookies").ForEach(func(key, value gjson.Result) bool {
			if key.String() == "lzkqow38189" {
				domain = "dppt." + info.Area + ".chinatax.gov.cn"
			} else if key.String() == "token" {
				domain = "tpass." + info.Area + ".chinatax.gov.cn"
			} else {
				domain = ".chinatax.gov.cn"
			}
			cookies = append(cookies, &proto.NetworkCookieParam{
				Name:   key.String(),
				Value:  value.String(),
				Domain: domain,
				Path:   "/",
			})
			return true
		})
		localStorage := map[string]string{}
		gdata.Get("localStorage").ForEach(func(key, value gjson.Result) bool {
			localStorage[key.String()] = value.String()
			return true
		})
		Session.Cookies = cookies
		Session.LocalStorage = localStorage
		//dpptURL = gdata.Get("redirectUri").String()
	}
	//if ctxValue := ctx.Value("website"); ctxValue != nil { //只有发票任务会传website
	//	// 写入浏览器
	//	name, err := LoadCookieFast(Session, p, BaseUri, info)
	//	if err != nil {
	//		fmt.Println(err.Error())
	//		return err
	//	}
	//	if name != info.ComName {
	//		return taxerr.CompanyNameError(name)
	//	}
	//} else {
	// 写入浏览器
	name, err := LoadCookie(Session, p, BaseUri, info)
	if err != nil {
		return err
	}
	if name != info.ComName {
		return taxerr.CompanyNameError(name)
	}
	//}
	return
}

func AesECBEncrypt(data map[string]any) []byte {
	jsonData, _ := json.Marshal(data)
	fmt.Println(string(jsonData))
	padded := make([]byte, 16)
	copy(padded, key)
	encryptData, err := openssl.AesECBEncrypt(jsonData, []byte(padded), openssl.PKCS5_PADDING)
	if err != nil {
		return []byte("")
	}
	jsonData, _ = json.Marshal(map[string]string{"data": base64.StdEncoding.EncodeToString(encryptData)})
	return jsonData
}
