package task

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"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/common/variable"
	"git.listensoft.net/tool/jspkit/logger"
	"git.listensoft.net/tool/jspkit/login"
	"git.listensoft.net/tool/jspkit/taxerr"
	"github.com/spf13/viper"
	"github.com/tidwall/gjson"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"time"
)

const taxMaxTime = 20 * time.Minute //超时默认20分钟

// GetContent 根据地区定制Content 设置超时时间
func GetContent(childCtx context.Context, address string, pdfTel string, ticker *time.Ticker) (childCtx1 context.Context) {
	if address == "shandong" || address == "neimenggu" || address == "jiangsu" { // 针对20分钟不够用的地区
		childCtx1, _ = context.WithTimeout(childCtx, 30*time.Minute)
	} else if address == "sichuan" || address == "chongqing" || address == "shanxi" || (address == "anhui") {
		childCtx1, _ = context.WithTimeout(childCtx, 40*time.Minute)
	} else if address == "fujian" || address == "beijing" || address == "qinghai" || address == "xiamen" {
		childCtx1, _ = context.WithTimeout(childCtx, 40*time.Minute)
	} else {
		childCtx1, _ = context.WithTimeout(childCtx, taxMaxTime)
	}
	if pdfTel != "" {
		//childCtx1, _ = context.WithTimeout(childCtx, 120*time.Minute) //四川的pdf采集 一个小时不够
		ticker = time.NewTicker(4 * time.Minute) // 每四分钟加五分钟的锁
		go func() {
			for t := range ticker.C { // 阻塞等待接收ticker发出的时间信号
				common.AddTelLockerX2(pdfTel, "300")
				logger.Info("Tick at:", t)
			}
		}()
	}
	return
}

// GetTaxTask 获取任务
func GetTaxTask(robotName string) (list []models.TaxTask, err error) {
	client := lxhttp.NewHttpClient()
	defer client.CloseIdleConnections()
	param := map[string]string{
		"robotName": robotName,
	}
	bys, err2 := lxhttp.POSTJson(client, variable.TaxTaskURL+"/api/v1/getRobotQueue", param, map[string]string{})
	if err2 != nil {
		return
	}
	data := gjson.GetBytes(bys, "data").String()
	list = []models.TaxTask{}
	err = json.Unmarshal([]byte(data), &list)
	return
}

// EndQueue 释放机器人
func EndQueue(robotName string) {
	client := lxhttp.NewHttpClient()
	defer client.CloseIdleConnections()
	param := map[string]string{
		"robotName": robotName,
	}
	bys, err2 := lxhttp.POSTJson(client, variable.TaxTaskURL+"/api/v1/endQueue", param, map[string]string{}) // https://task.listensoft.net
	if err2 != nil {
		return
	}
	logger.Info("endQueue - ", string(bys))
}

// GetRobotName 获取当前机器人名称
func GetRobotName() string {
	//环境变量中读取名称
	envRobotName := os.Getenv("robotName")
	logger.Info("envRobotName:", envRobotName)
	if envRobotName != "" {
		return envRobotName
	}
	//config中读取文件
	confRobotName := viper.GetString("robotName")
	logger.Info("confRobotName:", confRobotName)
	if confRobotName != "" { //如果是测试环境 固定一个 robotName 方便调试 一直获取一个任务
		return confRobotName
	}
	//读取不到默认文件夹名称
	dir, _ := os.Getwd()
	_, file := filepath.Split(dir)
	logger.Info("fileDIrRobotName:", file)
	return file
}

// 结束任务
func EndTask(ctx context.Context, tasks []models.TaxTask) {
	clientURL := variable.TaxTaskURL + "/api/v1/endTaskTax"
	for k, v := range tasks {
		symbolToRemove := ","
		// 使用Trim函数删除字符串两端的指定符号
		tasks[k].Result.BusinessImg = strings.Trim(v.Result.BusinessImg, symbolToRemove)
	}
	for _, task := range tasks {
		if (strings.Contains(task.Result.BusinessLog, "您当前认证等级不够") || strings.Contains(task.Result.BusinessLog, "认证等级无法访问该功能")) && task.LoginType == "新版登录" {
			task.Result.BusinessStatus = variable.TaxFail
			task.Result.BusinessLog = common.HandleError(ctx, taxerr.TaxRzDkErr).Error()
			login.RemoveLogin(models.CompanyInfo{Tel: strings.Split(task.Tel, "#")[0], Area: task.Address})
		}
		// 检查 如果截图lv《申报清册_有遗漏》 状态不是有遗漏 这边强制改成有遗漏 遇到别的情况再额外处理
		if task.TaskName == variable.TaxJcShenBao &&
			(task.Result.BusinessStatus != variable.TaxSuccessdOmit && task.Result.BusinessStatus != variable.TaxFail) &&
			strings.Contains(task.Result.BusinessImg, "申报清册_有遗漏") {
			task.Result.BusinessStatus = variable.TaxSuccessdOmit
			task.Result.BusinessLog = "申报清册有遗漏,请看截图" + task.Result.BusinessLog
		}
		if task.ReqNo == "" {
			logger.Info("跳过用于解锁的空任务：", task)
			continue
		}
		task.Result.ReqNo = task.ReqNo //reqNo 返回
		if task.Result.Status == 0 {   //如果没有状态 申报检查会带状态过来
			task.Result.Status = variable.TaxSuccess //默认任务成功
		}
		if !task.Result.BusinessStatus.Check() { //没有状态的话
			task.Result.BusinessStatus = variable.TaxFail                                             //失败
			task.Result.BusinessLog = common.HandleError(ctx, taxerr.NewWebStuckTitle(false)).Error() //提示不支持的任务
		}
		//if task.Result.BusinessStatus.Success() { //如果是成功的话
		//	task.Result.BusinessLog = "成功" //提示不支持的任务
		//}
		//if task.TaskName == variable.TaxCjInInvoice && strings.Contains(task.Result.BusinessLog, "请勾选认证后再次发起采集") {
		//	task.Result.BusinessStatus = variable.TaxSuccessNeedPay
		//}
		if strings.Contains(string(task.TaskName), `kk`) && task.Result.BusinessStatus != variable.TaxTiJiaoJinSan {
			if task.Result.BusinessStatus != variable.TaxSuccessPaid && task.Result.BusinessStatus != variable.TaxSuccessdPaid {
				task.Result.BusinessStatus = variable.TaxFail
			} else {
				if task.TaskName != variable.TaxKkShebao { //社保的扣款任务要保留原状态作为 系统扣款 和 非系统扣款
					task.Result.BusinessStatus = variable.TaxSuccess
				}
			}
		}
		bys, _ := json.Marshal(task.Result)
		logger.Info("结束任务：", string(bys))
		for i := 0; i < 6; i++ {
			logger.Info(time.Now(), fmt.Sprintf("-----------第%s次尝试endTaskTax", strconv.Itoa(i)))
			res, err := lxhttp.HttpClientPost(lxhttp.NewHttpClient(), clientURL, "application/json", bytes.NewReader(bys))
			if err != nil || strings.Contains(string(res), "Sorry") {
				logger.Error("任务结束请求错误:" + err.Error())
				time.Sleep(time.Second * 10)
				continue
			} else {
				logger.Info(time.Now(), fmt.Sprintf("-----------第%s次endTaskTax成功", strconv.Itoa(i)))
				logger.Info("任务结束发送到服务器返回结果:", string(res))
				break
			}
		}

	}
}

// =================================== 历史数据采集相关 ======================================

// 校验凭证出现的所有科目是否都在中间课余表中
func CheckSubjectCodes(midSubjects []models.HisSubject, Vouchers []models.HisVoucher) bool {
	var Map1 map[string]bool // 凭证的所有科目
	Map1 = make(map[string]bool, len(midSubjects))
	var Map2 map[string]bool // 中间课余表的所有科目
	Map2 = make(map[string]bool, len(midSubjects))
	for _, v1 := range Vouchers {
		for _, v2 := range v1.Items {
			if !Map1[v2.SubjectCode] {
				Map1[v2.SubjectCode] = true
			}
		}
	}
	for _, v := range midSubjects {
		if !Map2[v.SubjectCode] {
			Map2[v.SubjectCode] = true
		}
	}
	for v := range Map1 {
		if !Map2[v] {
			for _, v1 := range Vouchers {
				for _, v2 := range v1.Items {
					if v == v2.SubjectCode {
						logger.Info(v1.VoucherNo, v1.Period)
						break
					}
				}
			}
			logger.Info(v)
			return false
		}
	}
	return true
}

// 返回错误信息
func CheckSubjectCodesError(midSubjects []models.HisSubject, Vouchers []models.HisVoucher) (bool, string) {
	var Map1 map[string]bool // 凭证的所有科目
	Map1 = make(map[string]bool, len(midSubjects))
	var Map2 map[string]bool // 中间课余表的所有科目
	Map2 = make(map[string]bool, len(midSubjects))
	for _, v1 := range Vouchers {
		for _, v2 := range v1.Items {
			if !Map1[v2.SubjectCode] {
				Map1[v2.SubjectCode] = true
			}
		}
	}
	for _, v := range midSubjects {
		if !Map2[v.SubjectCode] {
			Map2[v.SubjectCode] = true
		}
	}
	for v := range Map1 {
		if !Map2[v] {
			msg := ""
			for _, v1 := range Vouchers {
				for _, v2 := range v1.Items {
					if v == v2.SubjectCode {
						msg = fmt.Sprintf("%s期%s凭证出现缺失%s科目", v1.Period, v1.VoucherNo, v)
						logger.Info(v1.VoucherNo, v1.Period)
						break
					}
				}
			}
			logger.Info(v)
			return false, msg
		}
	}
	return true, ""
}

func Unlocking(start time.Time, tasks []models.TaxTask) {
	reqs := []string{}
	for _, v := range tasks {
		reqs = append(reqs, strings.Split(v.ReqNo, "&")...)
	}
	req := strings.Join(reqs, "*")
	UnTels := make(map[string]bool, 1000)
	if len(tasks) < 1 {
		return
	}
	//工商的任务不在这里解锁了(避免影响到这个手机号下的税局申报任务，因为如果不加锁的话120秒是可能不够工商申报的，并发的话税局任务会一直挂掉)
	//如果想要工商任务快一点(客户嫌慢的话)，工商任务拿到的时候自己加锁，加锁时长要大于等待验证码的时间(确保收到验证码后解锁 解的是自己加的锁)，然后收到验证码的时候解锁
	for _, task := range tasks {
		if task.TaskName == variable.TaxCjGsnb || task.TaskName == variable.TaxSbGsnb {
			return
		}
	}
	// 采集pdf除外 因为超了20分钟就不解锁了 pdf统一上锁3600
	if (tasks[0].Address == "jiangsu" || tasks[0].Address == "henan") && tasks[0].TaskName != variable.TaxCjInvoicePdf { //&& (tasks[0].LoginType == "政务网登录" || tasks[0].LoginType == "免验证码登录")
		checkPass := true
		info, _ := GetEacComInfo(tasks[0])
		if info.Dlfs == "新版登录" && strings.Contains(tasks[0].Result.BusinessLog, "验证码接收失败") {
			logger.Info("结束该手机号剩余任务：" + info.Tel)
			common.CancelLeftTasks(info.Tel)
		}
		for _, task := range tasks {
			if strings.Contains(task.Result.BusinessLog, "超限") { //strings.Contains(task.Result.BusinessLog, "锁定") ||
				checkPass = false
			}
		}
		if tasks[0].Address == "henan" && checkPass {
			if !time.Now().After(start.Add(12 * time.Minute)) { //不超过7分钟的解锁
				tel := strings.Split(tasks[0].Tel, `#`)[0]
				if time.Since(start).Seconds() < 45 {
					itv := common.FloatToIntStr((45 - time.Since(start).Seconds()) / 1)
					logger.Info("加锁：" + tel + " " + itv)
					common.AddTelLockerX2(tel, itv)
					return
				}
				logger.Info("解锁：" + tel)
				common.AddTelLockerX2Req(tel, "-1", req)
			} else if tasks[0].TaskName == variable.TaxCjInvoicePdf { //pdf的任务，如果没有任务在执行也解锁
				tel := strings.Split(tasks[0].Tel, `#`)[0]
				status, err := common.GetTelTaskStatus(tel)
				if err != nil {
					logger.Info("获取手机号任务状态失败")
					return
				}
				if !status {
					logger.Info("解锁：" + tel)
					common.AddTelLockerX2Req(tel, "-1", req)
				}
				return
			}

		}
		if tasks[0].Address == "jiangsu" && !time.Now().After(start.Add(18*time.Minute)) && checkPass {
			tel := strings.Split(tasks[0].Tel, `#`)[0]
			if time.Since(start).Seconds() < 45 {
				itv := common.FloatToIntStr((45 - time.Since(start).Seconds()) / 1)
				logger.Info("加锁：" + tel + " " + itv)
				common.AddTelLockerX2(tel, itv)
				return
			}
			logger.Info("解锁：" + tel)
			common.AddTelLockerX2Req(tel, "-1", req)
		}
		return
	}
	for _, task := range tasks {
		info, _ := GetEacComInfo(task)
		//address := info.Area
		// 新版登录 收不到验证码撤销掉剩余的任务,避免一直发导致超限
		if info.Dlfs == "新版登录" && strings.Contains(task.Result.BusinessLog, "验证码接收失败") {
			logger.Info("结束该手机号剩余任务：" + info.Tel)
			common.CancelLeftTasks(info.Tel)
		}
		//
		{

			//// 新版=统一解锁
			//if (info.Dlfs == "新版登录" || info.Dlfs == "代理登录") && info.Tel != "" && !(strings.Contains(task.Result.BusinessLog, "超限") || strings.Contains(task.Result.BusinessLog, "发送短信过于频繁")) {
			//	if !UnTels[info.Tel] {
			//		UnTels[info.Tel] = true
			//	}
			//}
			//// zrridno统一解锁
			//if address == Hebei || address == Hainan || address == Yunnan || address == Shandong || address == Beijing || address == Xizang || address == "zhejiang" || address == "guangdong" || address == "jilin" {
			//	if info.Dlfs == "新版登录" {
			//		if !UnTels[info.Tel] {
			//			UnTels[info.Tel] = true
			//		}
			//	} else {
			//		if !UnTels[info.Zzridno] {
			//			UnTels[info.Zzridno] = true
			//		}
			//	}
			//}
			//// zrrxm解锁
			//if address == "ningxia" {
			//	if !UnTels[info.Zzrxm] {
			//		UnTels[info.Zzrxm] = true
			//	}
			//}
			//// 所有登陆方式都需要解锁的地区
			//if address == Shanxi || address == Jiangxi || address == Guangxi || address == Neimenggu || address == Xinjiang || address == Shenzhen || address == Henan || address == Anhui || address == Shaanxi || address == Hunan || address == Qingdao || address == Sichuan || address == Guizhou || address == Gansu || address == Dalian {
			//	if !UnTels[info.Tel] {
			//		UnTels[info.Tel] = true
			//	}
			//}
			////if (address == "tianjin" || address == "guangdong" || address == "zhejiang" || address == "hubei") && info.Dlfs == "新版登录" {
			////	if !UnTels[info.Zzridno+"_"+info.Area] {
			////		UnTels[info.Zzridno+"_"+info.Area] = true
			////	}
			////}
			//// 针对发送超限
			//if strings.Contains(task.Result.BusinessLog, "超限") || strings.Contains(task.Result.BusinessLog, "发送短信过于频繁") {
			//	common.AddTelLockerX2(info.Tel, "600")
			//}
			//// 针对新疆
			//if strings.Contains(task.Result.BusinessLog, "因上条短信验证码未正常使用，无法重新获取验证码，请您在5分钟后上条短信失效后") {
			//	common.AddTelLockerX2(info.Tel, "300")
			//}
		}
		// 现在直接用手机号解锁,因为不管用什么加锁都会加到tel字段上
		if info.Tel != "" {
			UnTels[info.Tel] = true
		}
		// 频繁加锁
		if strings.Contains(task.Result.BusinessLog, "短信发送申请过于频繁") || strings.Contains(task.Result.BusinessLog, "超限") || strings.Contains(task.Result.BusinessLog, "发送短信过于频繁") || strings.Contains(task.Result.BusinessLog, "因上条短信验证码未正常使用，无法重新获取验证码，请您在5分钟后上条短信失效后") {
			UnTels[info.Tel] = false
			common.AddTelLockerX2(info.Tel, "300") // 直接覆盖一个5分钟的锁
		}
	}
	for k := range UnTels {
		haspdf := false
		for _, v := range tasks {
			if v.TaskName == variable.TaxCjInvoicePdf {
				haspdf = true
				break
			}
		}
		if time.Since(start).Seconds() < 1195 || haspdf {
			logger.Info("开始时间:", start.Format("2006-01-02 15:04:05"), ";结束时间:", time.Now().Format("2006-01-02 15:04:05"), ";任务时长:", time.Since(start).Seconds())
			logger.Info("解锁：" + k)
			common.AddTelLockerX2Req(k, "-1", req)
		}
		//if strings.Contains(k, "anhui") {
		//	logger.Info("安徽暂时全解锁：" + k)
		//	common.AddTelLockerX2Req(k, "-1", req)
		//}
	}
}
