package models

import (
	"LAPP_LF_MOM_BACKEND/db"
	"LAPP_LF_MOM_BACKEND/utils"
	"errors"
	"github.com/go-xorm/xorm"
	"strconv"
	"strings"
	"time"
	"xorm.io/core"
)

type Snrtab struct {
	Finr             int    `xorm:"pk comment('工厂号') Int" json:"snrtab-finr"`
	Snrid            string `xorm:"pk comment('Id') VARCHAR(12)" json:"snrtab-snrid"`
	Descr            string `xorm:"comment('描述') VARCHAR(30)" json:"snrtab-descr"`
	Validfrom        string `xorm:"comment('有效起始日期') VARCHAR(8)" json:"snrtab-validfrom"`
	Validto          string `xorm:"comment('有效截至日期') VARCHAR(8)" json:"snrtab-validto"`
	Prefix           string `xorm:"comment('前缀') VARCHAR(20)" json:"snrtab-prefix"`
	Infix            string `xorm:"comment('中缀') VARCHAR(20)" json:"snrtab-infix"`
	Postfix          string `xorm:"comment('后缀') VARCHAR(20)" json:"snrtab-postfix"`
	Startnr          int    `xorm:"comment('流水号起始值') INT" json:"snrtab-startnr"`
	Endnr            int    `xorm:"comment('流水号截止值') INT" json:"snrtab-endnr"`
	Step             int    `xorm:"comment('步幅') INT" json:"snrtab-step"`
	Length           int    `xorm:"comment('长度') INT" json:"snrtab-length"`
	Nextnr           int    `xorm:"comment('下一流水号') INT" json:"snrtab-nextnr"`
	Lastnrcreate     string `xorm:"comment('上个序号创建时间') VARCHAR(14)" json:"snrtab-lastnrcreate"`
	Resetnrrule      string `xorm:"comment('序号重置规则') VARCHAR(10)" json:"snrtab-resetnrrule"`
	Overflowhandling string `xorm:"comment('序号溢出处理') VARCHAR(10)" json:"snrtab-overflowhandling"`
	Identifierformat string `xorm:"comment('流水号格式') VARCHAR(10)" json:"snrtab-identifierformat"`
	Datevariable     string `xorm:"comment('日期变量') VARCHAR(20)" json:"snrtab-datevariable"`
	Dateformat       string `xorm:"comment('日期格式') VARCHAR(14)" json:"snrtab-dateformat"`
	Identifierlayout string `xorm:"comment('标识符布局') VARCHAR(5)" json:"snrtab-identifierlayout"`
	Lastmodif        string `xorm:"comment('最近一次更改时间') VARCHAR(14)" json:"snrtab-lastmodif"`
	Lastuser         string `xorm:"comment('最近一次更改人') VARCHAR(20)" json:"snrtab-lastuser"`
	Credatuz         string `xorm:"comment('创建时间') VARCHAR(14)" json:"snrtab-credatuz"`
}

func (t *Snrtab) TableName() string {
	return "snrtab"
}

// 清除string字段的右侧空格
func (t *Snrtab) Clipped() {
	utils.TrimStruct(t, *t)
}

//增
func (t *Snrtab) Add() error {
	e := db.Eloquent.Master()
	countrole := new(Snrtab)
	affw, err := e.Table("snrtab").ID(core.PK{t.Finr, t.Snrid}).Count(countrole)
	if err != nil {
		return err
	}
	if affw > 0 {
		return errors.New("数据已经存在！")
	}
	_, err = e.Table("snrtab").Insert(t)
	if err != nil {
		return err
	}
	return nil
}

//删
func (t *Snrtab) Del() bool {
	e := db.Eloquent.Master()
	_, err := e.ID(core.PK{t.Finr, t.Snrid}).Delete(&Snrtab{})
	if err != nil {
		return false
	}
	return true
}

//改
func (t *Snrtab) Update() bool {
	e := db.Eloquent.Master()
	_, err := e.ID(core.PK{t.Finr, t.Snrid}).Update(t)
	if err != nil {
		return false
	}
	return true
}

//查
func (t *Snrtab) SelectOne() (Snrtab, error) {
	e := db.Eloquent.Master()
	var data Snrtab
	_, err := e.ID(core.PK{t.Finr, t.Snrid}).Get(&data)
	if err != nil {
		return data, err
	}
	return data, nil
}

//分页
func (t *Snrtab) GetPage(pageSize int, pageIndex int) ([]Snrtab, int, error) {
	data := make([]Snrtab, 0)
	e := db.Eloquent.Master()
	table := e.Table("snrtab").Where("finr = ? ", t.Finr)
	where := "where finr = " + "'" + utils.ValueToString(t.Finr, "") + "'"
	if !utils.ValueIsEmpty(t.Snrid) {
		table = table.And("snrid = ?", t.Snrid)
		where += " and snrid = " + "'" + t.Snrid + "'"
	}
	Offset := (pageIndex - 1) * pageSize
	err := e.SQL("SELECT TOP " + utils.ValueToString(pageSize, "") + " snrtab.* FROM snrtab " + where + " AND (convert(varchar(10),finr)+convert(varchar(40),snrid) NOT IN (SELECT TOP " + utils.ValueToString(Offset, "") + " convert(varchar(10),finr)+convert(varchar(40),snrid) FROM snrtab " + where + " ORDER BY credatuz DESC)) ORDER BY credatuz DESC").Find(&data)
	pcount := new(Snrtab)
	count, err := table.Count(pcount)
	if err != nil {
		return data, 0, err
	}
	for k, _ := range data {
		data[k].Clipped()
	}
	return data, int(count), nil
}

// 获取指定序列的下一个流水号
func  (t *Snrtab) GetNextSnr(snr string)(retsnr string, err error){
	var(
		snrtab Snrtab
		lastupdtime time.Time
		y, l_y, d, l_d, wk, l_wk int
		m,l_m 	time.Month
		layout []byte
		i, nextsnr int
	)

	snrtab = Snrtab{}
	snrtab.Snrid = snr
	snrtab.Finr = t.Finr
	if snrtab, err = snrtab.SelectOne(); err != nil{
		return
	}
	snrtab.Clipped()

	if snrtab.Lastnrcreate == ""{
		nextsnr = snrtab.Nextnr
	}else {
		if lastupdtime, err = utils.DateParse(snrtab.Lastnrcreate, "YmdHis"); err != nil {
			return
		}
		// 获取下一序列值
		y 		= time.Now().Year()
		m 		= time.Now().Month()
		d 		= time.Now().Day()
		_, wk 	= time.Now().ISOWeek()
		l_y 	= lastupdtime.Year()
		l_m 	= lastupdtime.Month()
		l_d 	= lastupdtime.Day()
		_, l_wk = lastupdtime.ISOWeek()
		switch strings.ToUpper(snrtab.Resetnrrule)  {
		case "DAILY":
			if y == l_y && m == l_m && wk == l_wk && d == l_d {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "WEEKLY":
			if y == l_y && m == l_m && wk == l_wk {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "MONTHLY":
			if y == l_y && m == l_m {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "YEARLY":
			if y == l_y {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "NEVER":
			nextsnr = snrtab.Nextnr
		default:
			nextsnr = snrtab.Nextnr
		}
	}

	// 组合返回值
	layout = []byte(snrtab.Identifierlayout)
	for i = 0; i < len(layout); i++ {
		switch string(layout[i]) {
		case "1": //前缀
			retsnr = retsnr + snrtab.Prefix
		case "2": //日期变量
			retsnr = retsnr + utils.Date(time.Now().Unix(), snrtab.Dateformat)
		case "3": //中缀
			retsnr = retsnr + snrtab.Infix
		case "4": //流水号
			if snrtab.Identifierformat == "CHAR" {
				retsnr = retsnr + utils.ConvInt2FormatString(nextsnr, snrtab.Length)
			}else{
				retsnr = retsnr + strconv.Itoa(nextsnr)
			}
		case "5": //后缀
			retsnr = retsnr + snrtab.Postfix
		}
	}
	//更新下一序列值
	// 处理数值超限
	snrtab.Nextnr 		= nextsnr + snrtab.Step
	snrtab.Lastnrcreate = utils.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
	snrtab.Lastmodif 	= utils.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
	if snrtab.Nextnr > snrtab.Endnr {
		switch strings.ToUpper(snrtab.Overflowhandling) {
		case "NO":
		case "RESET":
			snrtab.Nextnr = snrtab.Startnr
		}
	}

	if res := snrtab.Update(); !res {
		return
	}

	return
}


// 获取指定序列的下一个流水号
func  (t *Snrtab) GetNextSnrWithNum(session *xorm.Session, snr string, num int)(retsnr string, err error){
	var(
		snrtab Snrtab
		lastupdtime time.Time
		y, l_y, d, l_d, wk, l_wk int
		m,l_m 	time.Month
		layout []byte
		i, nextsnr int
	)

	snrtab = Snrtab{}
	snrtab.Snrid = snr
	snrtab.Finr = t.Finr
	if snrtab, err = snrtab.SelectOneWithSession(session); err != nil{
		return
	}
	snrtab.Clipped()
	t.Length = snrtab.Length

	if snrtab.Lastnrcreate == ""{
		nextsnr = snrtab.Nextnr
	}else {
		if lastupdtime, err = utils.DateParse(snrtab.Lastnrcreate, "YmdHis"); err != nil {
			return
		}
		// 获取下一序列值
		y 		= time.Now().Year()
		m 		= time.Now().Month()
		d 		= time.Now().Day()
		_, wk 	= time.Now().ISOWeek()
		l_y 	= lastupdtime.Year()
		l_m 	= lastupdtime.Month()
		l_d 	= lastupdtime.Day()
		_, l_wk = lastupdtime.ISOWeek()
		switch strings.ToUpper(snrtab.Resetnrrule)  {
		case "DAILY":
			if y == l_y && m == l_m && wk == l_wk && d == l_d {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "WEEKLY":
			if y == l_y && m == l_m && wk == l_wk {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "MONTHLY":
			if y == l_y && m == l_m {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "YEARLY":
			if y == l_y {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "NEVER":
			nextsnr = snrtab.Nextnr
		default:
			nextsnr = snrtab.Nextnr
		}
	}

	// 组合返回值
	layout = []byte(snrtab.Identifierlayout)
	for i = 0; i < len(layout); i++ {
		switch string(layout[i]) {
		case "1": //前缀
			retsnr = retsnr + snrtab.Prefix
		case "2": //日期变量
			retsnr = retsnr + utils.Date(time.Now().Unix(), snrtab.Dateformat)
		case "3": //中缀
			retsnr = retsnr + snrtab.Infix
		case "4": //流水号
			if snrtab.Identifierformat == "CHAR" {
				retsnr = retsnr + utils.ConvInt2FormatString(nextsnr, snrtab.Length)
			}else{
				retsnr = retsnr + strconv.Itoa(nextsnr)
			}
		case "5": //后缀
			retsnr = retsnr + snrtab.Postfix
		}
	}
	//更新下一序列值
	// 处理数值超限
	snrtab.Nextnr 		= nextsnr + snrtab.Step * num
	snrtab.Lastnrcreate = utils.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
	snrtab.Lastmodif 	= utils.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
	if snrtab.Nextnr > snrtab.Endnr {
		switch strings.ToUpper(snrtab.Overflowhandling) {
		case "NO":
		case "RESET":
			snrtab.Nextnr = snrtab.Startnr
		}
	}
	if err = snrtab.UpdateWithSession(session); err != nil {
		return "", err
	}

	return
}


//改
func (t *Snrtab) UpdateWithSession(session *xorm.Session) error {
	_, err := session.ID(core.PK{t.Finr, t.Snrid}).Update(t)
	if err != nil {
		return err
	}
	return nil
}


// 获取指定序列的下一个流水号
func  (t *Snrtab) GetNextSnrWithSession(session *xorm.Session, snr string)(retsnr string, err error){
	var(
		snrtab Snrtab
		lastupdtime time.Time
		y, l_y, d, l_d, wk, l_wk int
		m,l_m 	time.Month
		layout []byte
		i, nextsnr int
	)

	snrtab = Snrtab{}
	snrtab.Snrid = snr
	snrtab.Finr = t.Finr
	if snrtab, err = snrtab.SelectOneWithSession(session); err != nil{
		return
	}
	snrtab.Clipped()

	if snrtab.Lastnrcreate == ""{
		nextsnr = snrtab.Nextnr
	}else {
		if lastupdtime, err = utils.DateParse(snrtab.Lastnrcreate, "YmdHis"); err != nil {
			return
		}
		// 获取下一序列值
		y 		= time.Now().Year()
		m 		= time.Now().Month()
		d 		= time.Now().Day()
		_, wk 	= time.Now().ISOWeek()
		l_y 	= lastupdtime.Year()
		l_m 	= lastupdtime.Month()
		l_d 	= lastupdtime.Day()
		_, l_wk = lastupdtime.ISOWeek()
		switch strings.ToUpper(snrtab.Resetnrrule)  {
		case "DAILY":
			if y == l_y && m == l_m && wk == l_wk && d == l_d {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "WEEKLY":
			if y == l_y && m == l_m && wk == l_wk {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "MONTHLY":
			if y == l_y && m == l_m {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "YEARLY":
			if y == l_y {
				nextsnr = snrtab.Nextnr
			}else{
				nextsnr = snrtab.Startnr
			}
		case "NEVER":
			nextsnr = snrtab.Nextnr
		default:
			nextsnr = snrtab.Nextnr
		}
	}

	// 组合返回值
	layout = []byte(snrtab.Identifierlayout)
	for i = 0; i < len(layout); i++ {
		switch string(layout[i]) {
		case "1": //前缀
			retsnr = retsnr + snrtab.Prefix
		case "2": //日期变量
			retsnr = retsnr + utils.Date(time.Now().Unix(), snrtab.Dateformat)
		case "3": //中缀
			retsnr = retsnr + snrtab.Infix
		case "4": //流水号
			if snrtab.Identifierformat == "CHAR" {
				retsnr = retsnr + utils.ConvInt2FormatString(nextsnr, snrtab.Length)
			}else{
				retsnr = retsnr + strconv.Itoa(nextsnr)
			}
		case "5": //后缀
			retsnr = retsnr + snrtab.Postfix
		}
	}
	//更新下一序列值
	// 处理数值超限
	snrtab.Nextnr 		= nextsnr + snrtab.Step
	snrtab.Lastnrcreate = utils.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
	snrtab.Lastmodif 	= utils.Date(time.Now().Unix(), "YYYYMMDDHHmmss")
	if snrtab.Nextnr > snrtab.Endnr {
		switch strings.ToUpper(snrtab.Overflowhandling) {
		case "NO":
		case "RESET":
			snrtab.Nextnr = snrtab.Startnr
		}
	}

	if err = snrtab.UpdateWithSession(session); err != nil {
		return
	}
	return
}


//查
func (t *Snrtab) SelectOneWithSession(session *xorm.Session) (Snrtab, error) {
	var data Snrtab
	_, err := session.ID(core.PK{t.Finr, t.Snrid}).Get(&data)
	if err != nil {
		return data, err
	}
	return data, nil
}
