package CheckYbjc

import (
	"fmt"
	"git.listensoft.net/tool/jspkit/common"
	"git.listensoft.net/tool/jspkit/common/models/sb"
	"git.listensoft.net/tool/jspkit/common/variable"
	"git.listensoft.net/tool/jspkit/logger"
	"git.listensoft.net/tool/jspkit/taxerr"
	"reflect"
	"strings"
)

func CheckVatByYbjc(Data string, vat []sb.GsVat, fb1 []sb.GsVatAttach1, fb2 []sb.GsVatAttach2, fb3 []sb.GsVatAttach3, fb4 []sb.GsVatAttach4, fb5 []sb.GsVatAttach5, jm []sb.GsVatJsxm) (status int, editTable string, errLog string) {
	vats := []sb.GsVat{}
	common.GetData(variable.GsVat, Data, &vats)
	var attach1s []sb.GsVatAttach1
	common.GetData(variable.GsVatAttach1, Data, &attach1s)
	var attach2s []sb.GsVatAttach2
	common.GetData(variable.GsVatAttach2, Data, &attach2s)
	var attach3s []sb.GsVatAttach3
	common.GetData(variable.GsVatAttach3, Data, &attach3s)
	var attach4s []sb.GsVatAttach4
	common.GetData(variable.GsVatAttach4, Data, &attach4s)
	var vatfjs []sb.GsVatAttach5
	common.GetData(variable.GsVatAttach5, Data, &vatfjs)
	if len(vatfjs) != 3 {
		panic(taxerr.NewUser("附加税生成错误！"))
	}
	var gs_vat_qt sb.GsVatQt
	common.GetData(variable.GsVatQt, Data, &gs_vat_qt)
	var gsVatJsxm []sb.GsVatJsxm
	common.GetData(variable.GsVatJsxm, Data, &gsVatJsxm)
	var jsxm []sb.GsVatJsxm
	for _, v := range gsVatJsxm {
		if v.Type == 1 && (common.StrToFloat(v.Qcye) != 0 || common.StrToFloat(v.Qmye) != 0 || common.StrToFloat(v.Bqfse) != 0 || common.StrToFloat(v.Bqydjse) != 0 || common.StrToFloat(v.Bqsjdjse) != 0) {
			jsxm = append(jsxm, v)
		}
	}
	var ckms []sb.GsVatJsxm //出口免税
	for _, v := range gsVatJsxm {
		if v.Type == 2 {
			ckms = append(ckms, v)
			break
		}
	}
	var kjfw []sb.GsVatJsxm //       其中：跨境服务
	for _, v := range gsVatJsxm {
		if v.Type == 3 {
			kjfw = append(kjfw, v)
			break
		}
	}
	var msxm []sb.GsVatJsxm
	for _, v := range gsVatJsxm {
		if v.Type == 4 && (common.StrToFloat(v.Qcye) != 0 || common.StrToFloat(v.Qmye) != 0 || common.StrToFloat(v.Bqfse) != 0 || common.StrToFloat(v.Bqydjse) != 0 || common.StrToFloat(v.Bqsjdjse) != 0) {
			msxm = append(msxm, v)
		}
	}
	{

	}

	return 1, "", ""
}

// CheckWpsrLost 无票收入负数发票 税局主表 系统主表 系统附表一；正数发票可以在CheckVat返回2 重新填表
func CheckWpsrLost(vat []sb.GsVat, baseVat []sb.GsVat, attach1 []sb.GsVatAttach1) bool {
	// 先判断附表一是不是有未开具发票
	Check1 := false
	for _, v := range attach1 {
		if common.StrToFloat(v.WkjfpXxynse) != 0 || common.StrToFloat(v.WkjfpXse) != 0 {
			logger.Info(`当前企业含有负数未开具发票,系统附表一数据:`, v.WkjfpXse, v.WkjfpXxynse)
			Check1 = true
			break
		}
	}
	// 在判断 主表的减免
	Check2 := false
	if common.StrToFloat(baseVat[0].Xxse) < common.StrToFloat(vat[0].Xxse) {
		Check2 = true
	}
	Check3 := true
	// 还是留几个强制校验
	{
		if common.StrToFloat(vat[0].Jxse) > common.StrToFloat(baseVat[0].Jxse) {
			Check3 = false
		}
		if common.StrToFloat(vat[0].Sqldse) != common.StrToFloat(baseVat[0].Sqldse) {
			Check3 = false
		}
		if common.StrToFloat(vat[0].Qcwjse) != common.StrToFloat(baseVat[0].Qcwjse) {
			Check3 = false
		}
	}

	if Check1 && Check2 && Check3 {
		logger.Info("当前企业含有负数未开具发票:主表数据", baseVat[0].Xxse, vat[0].Xxse)
		return true
	}
	return false
}

func CheckVat(vat []sb.GsVat, baseVat []sb.GsVat) (status int, errLog string) {
	status = 1
	var errLogs []string
	// 强制校验
	{
		i := 0
		var Prefix = ""
		switch i {
		case 0:
			Prefix = "一般纳税人主表-一般项目本月数-"
		case 1:
			Prefix = "一般纳税人主表-一般项目本年累计-"
		case 2:
			Prefix = "一般纳税人主表-即征即退项目本月数-"
		case 3:
			Prefix = "一般纳税人主表-即征即退项目本年累计-"
		}
		//if common.StrToFloat(vat[i].Asysljsxse) != common.StrToFloat(baseVat[i].Asysljsxse) {
		//	errLogs = append(errLogs, MakeMsg(Prefix+"（一）按适用税率计税销售额", vat[i].Asysljsxse, baseVat[i].Asysljsxse))
		//}
		if common.StrToFloat(baseVat[i].Xxse) < common.StrToFloat(vat[i].Xxse) {
			errLogs = append(errLogs, MakeMsg(Prefix+"销项税额", vat[i].Xxse, baseVat[i].Xxse))
		}
		if common.StrToFloat(vat[i].Jxse) > common.StrToFloat(baseVat[i].Jxse) {
			errLogs = append(errLogs, MakeMsg(Prefix+"进项税额", vat[i].Jxse, baseVat[i].Jxse))
		}
		if common.StrToFloat(vat[0].Sqldse) != common.StrToFloat(baseVat[0].Sqldse) {
			errLogs = append(errLogs, MakeMsg("一般纳税人主表一 一般项目本月数-上期留抵税额", vat[0].Sqldse, baseVat[0].Sqldse))
		}
		if common.StrToFloat(vat[0].Qcwjse) != common.StrToFloat(baseVat[0].Qcwjse) {
			errLogs = append(errLogs, MakeMsg("一般纳税人主表一 一般项目本月数-期初未缴税额", vat[0].Qcwjse, baseVat[0].Qcwjse))
		}
		//if common.StrToFloat(vat[i].Bqybtse) != common.StrToFloat(baseVat[i].Bqybtse) {
		//	errLogs = append(errLogs, MakeMsg(Prefix+"本期应补(退)税额", vat[i].Bqybtse, baseVat[i].Bqybtse))
		//}
		// 强制校验失败直接返回
		if len(errLogs) > 0 {
			return 3, strings.Join(errLogs, ",")
		}
	}
	for i := 0; i < 4; i++ {
		// 非强制校验
		{
			var KeyName = []string{
				"Asysljsxse",
				"Yshwxse",
				"Yslwxse",
				"Xxse",
				"Jxse",
				//"Sqldse",
				"Ynsehj",
				//"Qcwjse",

				"Qmwjse",
				"Bqybtse",
				"Cjs",
				"Jyf",
				"Dfjyf",
			}
			v1 := reflect.ValueOf(vat[0])
			v2 := reflect.ValueOf(baseVat[0])
			for _, v := range KeyName {
				if common.StrToFloat(v1.FieldByName(v).String()) != common.StrToFloat(v2.FieldByName(v).String()) {
					logger.Info("主表对比不通过：" + v)
					status = 2
					break
				}
			}
		}
	}
	if len(errLogs) > 0 {
		status = 3
		errLog = strings.Join(errLogs, ",")
	}
	return status, errLog
}

func CheckAttach1(fb1 []sb.GsVatAttach1, attach1 []sb.GsVatAttach1) (status int, errLog string) {
	status = 1
	var errLogs []string
	attach1[0].Jshj = "0" // 这个数据暂时置空 因为系统会计算出来但是税局是---
	// 非强制校验
	{

		var KeyName = []string{
			"KjskzzszyfpXse",
			"KjskzzszyfpXxynse",
			"WkjfpXse",
			"WkjfpXxynse",
			"KjqtfpXse",
			"KjqtfpXxynse",
			"Nsjctzdxse",
			"NsjctzXxynse",
		}
		for i := range attach1 {
			r1 := reflect.ValueOf(fb1[i])
			r2 := reflect.ValueOf(attach1[i])
			for _, key_name := range KeyName {
				if common.StrToFloat(r1.FieldByName(key_name).String()) != common.StrToFloat(r2.FieldByName(key_name).String()) {
					status = 2
					break
				}
			}
		}
		if common.StrToFloat(fb1[0].Xse) != common.StrToFloat(attach1[0].Xse) {
			if status != 2 {
				status = 2
			}
		}
		if common.StrToFloat(fb1[0].HjXxynse) != common.StrToFloat(attach1[0].HjXxynse) {
			if status != 2 {
				status = 2
			}
		}
	}
	if len(errLogs) > 0 {
		status = 3
		errLog = strings.Join(errLogs, ",")
	}
	return status, errLog
}

func CheckAttach2(fb2 []sb.GsVatAttach2, attach2 []sb.GsVatAttach2) (status int, errLog string) {
	status = 1
	var errLogs []string

	// 非强制校验
	{
		//期初已认证相符但未申报抵扣
		if common.StrToFloat(fb2[24].Je) != common.StrToFloat(attach2[24].Je) {
			errLogs = append(errLogs, fmt.Sprintf("附表二:期初已认证相符但未申报抵扣金额不一致:税局为%s系统为%s", fb2[24].Je, attach2[24].Je))
		}
		for i := range attach2 {
			// 三个都判断
			r1 := reflect.ValueOf(fb2[i])
			r2 := reflect.ValueOf(attach2[i])
			if i == 0 || i == 1 || i == 5 || i == 34 {
				for _, key_name := range []string{"Fs", "Je", "Se"} {
					if common.StrToFloat(r1.FieldByName(key_name).String()) != common.StrToFloat(r2.FieldByName(key_name).String()) {
						status = 2
						break
					}
				}
			}
			if status == 2 {
				break
			}
			if i > 11 && i < 23 {
				if common.StrToFloat(r1.FieldByName("Se").String()) != common.StrToFloat(r2.FieldByName("Se").String()) {
					status = 2
					break
				}
			}
			if status == 2 {
				break
			}
		}
	}
	if len(errLogs) > 0 {
		status = 3
		errLog = strings.Join(errLogs, ",")
	}
	return status, errLog
}
func CheckAttach3Cq(fb3 []sb.GsVatAttach3, attach3 []sb.GsVatAttach3) (status int, errLog string) {
	// 暂时没有校验
	//return 1, ""
	status = 1
	var errLogs []string
	// 非强制校验
	{
		for i := 0; i < len(attach3); i++ {
			status1 := ForeachStruct(fb3[i], attach3[i])
			if status != 2 {
				status = status1
			}
		}
	}
	if len(errLogs) > 0 {
		status = 3
		errLog = strings.Join(errLogs, ",")
	}
	return status, errLog
}
func CheckAttach3(fb3 []sb.GsVatAttach3, attach3 []sb.GsVatAttach3) (status int, errLog string) {
	// 暂时没有校验
	return 1, ""
	status = 1
	var errLogs []string
	// 非强制校验
	{
		for i := 0; i < len(attach3); i++ {
			status1 := ForeachStruct(fb3[i], attach3[i])
			if status != 2 {
				status = status1
			}
		}
	}
	if len(errLogs) > 0 {
		status = 3
		errLog = strings.Join(errLogs, ",")
	}
	return status, errLog
}
func CheckAttach4(fb4 []sb.GsVatAttach4, attach4 []sb.GsVatAttach4) (status int, errLog string) {
	status = 1
	var errLogs []string
	// 非强制校验
	{
		var KeyName = []string{
			"Bqsjdjse",
			"Bqfse",
			"Bqsjjjdkjxse",
			"Bqkjjdkjxse",
			"Qcye",
		}
		for i := 0; i < len(attach4); i++ {
			r1 := reflect.ValueOf(fb4[i])
			r2 := reflect.ValueOf(attach4[i])
			for _, key_name := range KeyName {
				if common.StrToFloat(r1.FieldByName(key_name).String()) != common.StrToFloat(r2.FieldByName(key_name).String()) {
					status = 2
					break
				}
			}
		}
	}
	if len(errLogs) > 0 {
		status = 3
		errLog = strings.Join(errLogs, ",")
	}
	return status, errLog
}
func CheckAttach5(fb5 []sb.GsVatAttach5, attach5 []sb.GsVatAttach5) (status int, errLog string) {
	status = 1
	// 非强制校验
	{
		var KeyNAme = []string{
			"Zzsse",
			"Ldtsbqkce",
			"Bqybtse",
		}
		for _, v1 := range attach5 {
			for _, v2 := range fb5 {
				if v1.ZsxmDm == v2.ZsxmDm {
					r1 := reflect.ValueOf(v1)
					r2 := reflect.ValueOf(v2)
					for _, key_name := range KeyNAme {
						if common.StrToFloat(r1.FieldByName(key_name).String()) != common.StrToFloat(r2.FieldByName(key_name).String()) {
							status = 2
							break
						}
					}
					if status == 2 {
						break
					}
				}
			}
			if status == 2 {
				break
			}
		}
	}
	var errLogs []string
	if len(errLogs) > 0 {
		status = 3
		errLog = strings.Join(errLogs, ",")
	}
	return status, errLog
}
func CheckJm(jm []sb.GsVatJsxm, Jm []sb.GsVatJsxm) (status int, errLog string) {
	status = 1
	var errLogs []string
	var jsxm1 []sb.GsVatJsxm
	for _, v := range jm {
		if v.Type == 1 && (common.StrToFloat(v.Qcye) != 0 || common.StrToFloat(v.Qmye) != 0 || common.StrToFloat(v.Bqfse) != 0 || common.StrToFloat(v.Bqydjse) != 0 || common.StrToFloat(v.Bqsjdjse) != 0) {
			jsxm1 = append(jsxm1, v)
		}
	}
	var ckms1 []sb.GsVatJsxm //出口免税
	for _, v := range jm {
		if v.Type == 2 {
			ckms1 = append(ckms1, v)
			break
		}
	}
	var kjfw1 []sb.GsVatJsxm //       其中：跨境服务
	for _, v := range jm {
		if v.Type == 3 {
			kjfw1 = append(kjfw1, v)
			break
		}
	}
	var msxm1 []sb.GsVatJsxm
	for _, v := range jm {
		if v.Type == 4 && (common.StrToFloat(v.Qcye) != 0 || common.StrToFloat(v.Qmye) != 0 || common.StrToFloat(v.Bqfse) != 0 || common.StrToFloat(v.Bqydjse) != 0 || common.StrToFloat(v.Bqsjdjse) != 0) {
			msxm1 = append(msxm1, v)
		}
	}

	var jsxm2 []sb.GsVatJsxm
	for _, v := range Jm {
		if v.Type == 1 && (common.StrToFloat(v.Qcye) != 0 || common.StrToFloat(v.Qmye) != 0 || common.StrToFloat(v.Bqfse) != 0 || common.StrToFloat(v.Bqydjse) != 0 || common.StrToFloat(v.Bqsjdjse) != 0) {
			jsxm2 = append(jsxm2, v)
		}
	}
	var ckms2 []sb.GsVatJsxm //出口免税
	for _, v := range Jm {
		if v.Type == 2 {
			ckms2 = append(ckms2, v)
			break
		}
	}
	var kjfw2 []sb.GsVatJsxm //       其中：跨境服务
	for _, v := range Jm {
		if v.Type == 3 {
			kjfw2 = append(kjfw2, v)
			break
		}
	}
	var msxm2 []sb.GsVatJsxm
	for _, v := range Jm {
		if v.Type == 4 && (common.StrToFloat(v.Qcye) != 0 || common.StrToFloat(v.Qmye) != 0 || common.StrToFloat(v.Bqfse) != 0 || common.StrToFloat(v.Bqydjse) != 0 || common.StrToFloat(v.Bqsjdjse) != 0) {
			msxm2 = append(msxm2, v)
		}
	}

	// 非强制校验
	{
		// 减税项目
		if len(jsxm1) != len(jsxm2) {
			status = 2
			//errLogs = append(errLogs, fmt.Sprintf("税局减税项目有%d条系统有%d条", len(jsxm1), len(jsxm2)))
		}
		for _, v1 := range jsxm1 {
			find := false
			for _, v2 := range jsxm2 {
				if v1.SbJmxzdmJmHm == v2.SbJmxzdmJmHm {
					find = true
					if common.StrToFloat(v1.Qcye) == common.StrToFloat(v2.Qcye) && common.StrToFloat(v1.Qmye) == common.StrToFloat(v2.Qmye) && common.StrToFloat(v1.Bqfse) == common.StrToFloat(v2.Bqfse) && common.StrToFloat(v1.Bqydjse) == common.StrToFloat(v2.Bqydjse) {
						status = 1
					} else {
						status = 2
					}
					break
				}

			}
			if !find {
				status = 2
				//errLogs = append(errLogs, fmt.Sprintf("税局减税项目:%s 为在系统中找到,请核实", len(jsxm1), len(jsxm2)))
			}
		}
		// 出口
		if common.StrToFloat(ckms1[0].Qcye) != common.StrToFloat(ckms2[0].Qcye) {
			status = 2
		}

		// 跨境
		if (len(kjfw1) == len(kjfw2)) && len(kjfw1) > 0 && len(kjfw2) > 0 {
			if common.StrToFloat(kjfw1[0].Qcye) != common.StrToFloat(kjfw2[0].Qcye) {
				status = 2
			}
		}
		// 免税项目
		if len(msxm1) != len(msxm2) {
			status = 2
			//errLogs = append(errLogs, fmt.Sprintf("税局免税项目有%d条系统有%d条", len(msxm1), len(msxm2)))
		}
		for _, v1 := range msxm1 {
			find := false
			for _, v2 := range msxm2 {
				if v1.SbJmxzdmJmHm == v2.SbJmxzdmJmHm {
					find = true
					if common.StrToFloat(v1.Qcye) == common.StrToFloat(v2.Qcye) && common.StrToFloat(v1.Qmye) == common.StrToFloat(v2.Qmye) && common.StrToFloat(v1.Bqfse) == common.StrToFloat(v2.Bqfse) && common.StrToFloat(v1.Bqydjse) == common.StrToFloat(v2.Bqydjse) {
						if status != 2 {
							status = 1
						}
					} else {
						status = 2
					}
					break
				}

			}
			if !find {
				status = 2
				//errLogs = append(errLogs, fmt.Sprintf("税局免税项目:%s 为在系统中找到,请核实", len(jsxm1), len(jsxm2)))
			}
		}
	}
	if len(errLogs) > 0 {
		status = 3
		errLog = strings.Join(errLogs, ",")
	}
	return status, errLog
}

// 对比结构体数据
func ForeachStruct(obj1 interface{}, obj2 interface{}) (status int) {
	status = 1
	t1 := reflect.TypeOf(obj1)
	v1 := reflect.ValueOf(obj1)
	t2 := reflect.TypeOf(obj2)
	v2 := reflect.ValueOf(obj2)
	for k := 0; k < t1.NumField(); k++ {
		KeyName := t1.Field(k).Name
		if KeyName == "GsMainId" || KeyName == "ID" || KeyName == "GsBaseModel" || KeyName == "Type" || KeyName == "JmxzdmId" || KeyName == "JmxzdmSb" {
			continue
		}
		//fmt.Println(KeyName)
		Value := common.StrToFloat(v1.Field(k).Interface().(string))
		for j := 0; j < t2.NumField(); j++ {
			if KeyName == t2.Field(j).Name {
				if Value != common.StrToFloat(v2.Field(j).Interface().(string)) {
					logger.Info(KeyName, "-对比失败[税局为:", Value, "系统为:", common.StrToFloat(v2.Field(j).Interface().(string)), "]")
					status = 2
				}
				break
			}
		}
	}
	return status
}

// str:错误内容 data1税局数据 data2系统数据
func MakeMsg(str, data1, data2 string) string {
	return fmt.Sprintf(str+"数据对比失败:[税局为:%s;系统为:%s;]", data1, data2)
}

// 校验减免明细有数 但是没有代码的
func CheckJmDm(all []sb.GsVatJsxm) error {
	for _, v := range all {
		if v.Type != 2 && v.Type != 3 {
			if v.SbJmxzdmJmDm == "" && v.SbJmxzdmJmHm == "" && (common.StrToFloat(v.Qcye) != 0 || common.StrToFloat(v.Bqfse) != 0 || common.StrToFloat(v.Bqydjse) != 0 || common.StrToFloat(v.Bqsjdjse) != 0 || common.StrToFloat(v.Qmye) != 0) {
				return taxerr.NewUserV3("存在未填写减免代码的减免项目", "请手动补充后重试")
			}
		}
	}
	return nil
}

/*
逻辑:
	1.读取发票后采集6张表 生成和系统数据一样的结构体并且除减免表外的其他表机构提数组长度务必相等
	2.调用上面方法对比每个表 errLog为强制校验
	3.
		当所有表对比后返回的状态都是status=1时 直接申报即可
		当某张表对比后返回status=2时 所有表按系统数据重填神申报
		当某张表对比后返回status=3时 直接返回错误 taxerr.NewUser(errlog)
注意点:
	1.附表一按行采集完22行后 单独把第三行插到23行中
	2.附表二按系统顺序采集！！！！！！可以看河南内蒙的申报填表注释代码
	3.当所有表校验完status!=3后再去判断有一个表status=2就需要重新填所有表
	4.当所有表校验完status=1才能直接点击申报
传入参数:
	第一个参数是税局采集的数据
	第二个参数是任务的数据
返回参数:
	status:
		1 当前表所有数据校验通过
		2 当前表普通检验不通过 应根据系统的数据填写到报表上
		3 当前表强之校验不通过 直接返回errLog的错误
	errLog：
		目前只返回强制校验错误提示
*/
