package models

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

type PmWo struct {
	Finr          int           `json:"finr" xorm:"not null pk INT(4)"`
	Maintwoid     string        `json:"maintwoid" xorm:"not null pk VARCHAR(18)"`
	Mainservicenr string        `json:"mainservicenr" xorm:"not null VARCHAR(18)"`
	Descr         string        `json:"descr" xorm:"not null VARCHAR(40)"`
	Status        int           `json:"status" xorm:"not null INT(4)"`
	Priority      int           `json:"priority" xorm:"not null SMALLINT(2)"`
	Assetid       int           `json:"assetid" xorm:"not null INT(4)"`
	Plbegdat      string        `json:"plbegdat" xorm:"not null VARCHAR(8)"`
	Plenddat      string        `json:"plenddat" xorm:"not null VARCHAR(8)"`
	Needschedule  int           `json:"needschedule" xorm:"not null INT(4)"`
	Maintimelen   float64       `json:"maintimelen" xorm:"not null DECIMAL(16,6)"`
	Timeunit      string        `json:"timeunit" xorm:"not null VARCHAR(5)"`
	Schedbegtime  string        `json:"schedbegtime" xorm:"not null VARCHAR(14)"`
	Schedendtime  string        `json:"schedendtime" xorm:"not null VARCHAR(14)"`
	Actbegtime    string        `json:"actbegtime" xorm:"not null VARCHAR(14)"`
	Actendtime    string        `json:"actendtime" xorm:"not null VARCHAR(14)"`
	Assignedto    string        `json:"assignedto" xorm:"not null VARCHAR(1)"`
	Operator      int           `json:"operator" xorm:"not null INT(4)"`
	Vendor        int           `json:"vendor" xorm:"not null INT(4)"`
	Mainttype     string        `json:"mainttype" xorm:"not null VARCHAR(14)"`
	Costcenterid  string        `json:"costcenterid" xorm:"not null VARCHAR(12)"`
	Poid          string        `json:"poid" xorm:"not null VARCHAR(18)"`
	Lastmodif     string        `json:"lastmodif" xorm:"not null VARCHAR(14)"`
	Lastuser      string        `json:"lastuser" xorm:"not null VARCHAR(20)"`
	Credatuz      string        `json:"credatuz" xorm:"not null VARCHAR(14)"`
	UrgencyDegree int           `json:"urgencyDegree" xorm:"-"`
	Valst         []PmWoAttrlst `json:"valst" xorm:"-"`
}

const (
	UngencyStatusNot int = iota
	UngencyStatusYes
)

type PmWoService struct {
	PmWo      `xorm:"extends"`
	PmService `xorm:"extends"`
}

func (t *PmWo) TableName() string {
	return "pm_wo"
}

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

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

	if err != nil {
		return err
	}
	return nil
}

//增
func (t *PmWo) AddSession(session *xorm.Session) error {
	count := new(PmWo)
	affw, err := session.Table("pm_wo").ID(core.PK{t.Finr, t.Maintwoid}).Count(count)
	if err != nil {
		return err
	}
	if affw > 0 {
		return errors.New("数据已经存在！")
	}
	_, err = session.Table("pm_wo").Insert(t)

	if err != nil {
		return err
	}
	return nil
}

func (t *PmWo) InsertOne() error {
	engine := db.Eloquent.Master()
	session := engine.NewSession()
	defer session.Close()
	// add Begin() before any action
	err := session.Begin()
	if err != nil {
		return err
	}
	now := time.Now()
	snr := new(Snrtab)
	snr.Finr = t.Finr
	//生成ID
	woid, err := snr.GetNextSnrWithSession(session, "WOID")
	if err != nil {
		session.Rollback()
		return errors.New("生成Maintwoid出错:" + err.Error())
	}
	//符合逻辑生成维护工单
	pm := new(PmWo)
	pm.Finr = t.Finr
	pm.Maintwoid = woid
	pm.Mainservicenr = t.Mainservicenr
	pm.Descr = t.Descr
	pm.Status = 26
	pm.Priority = t.Priority
	pm.Assetid = t.Assetid
	pm.Plbegdat = utils.TimeFormat(now, "yyyyMMdd")
	pm.Schedbegtime = utils.TimeFormat(now, "yyyyMMddHHmmss")
	pm.Schedendtime = utils.TimeFormat(now, "yyyyMMddHHmmss")
	pm.Mainttype = t.Mainttype
	pm.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
	pm.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
	err = pm.AddSession(session)
	if err != nil {
		session.Rollback()
		return err
	}
	me := new(PmServiceAttrlst)
	me.Finr = t.Finr
	me.Mainserviceid = t.Mainservicenr
	data, err := me.SelectAll()
	if err != nil {
		session.Rollback()
		return err
	}
	//生成属性
	for _, v := range data {
		at := new(PmWoAttrlst)
		at.Finr = v.Finr
		at.Descr = v.Descr
		at.Mainservicenr = v.Mainserviceid
		at.Maintwoid = woid
		at.Pos = v.Pos
		at.Parameter = v.Parameter
		at.Paravalue = v.Paravalue
		at.Attrnr = v.Attrnr
		at.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
		at.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
		err := at.AddSession(session)
		if err != nil {
			session.Rollback()
			return err
		}
	}
	session.Commit()
	return nil
}

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

//改
func (t *PmWo) Update() error {
	e := db.Eloquent.Master()

	var data PmWo
	_, err := e.ID(core.PK{t.Finr, t.Maintwoid}).Get(&data)
	if err != nil {
		return err
	}
	_, err = e.ID(core.PK{t.Finr, t.Maintwoid}).Update(t)
	if err != nil {
		return err
	}
	if data.Status != t.Status {
		snr := new(Snrtab)
		snr.Finr = 100
		//生成ID
		woreid, _ := snr.GetNextSnr("Worecnr")
		//添加记录
		pm := new(PmWostatus)
		pm.Finr = t.Finr
		pm.Maintwoid = t.Maintwoid
		pm.Statusfrom = data.Status
		pm.Statusto = t.Status
		pm.Worecnr = utils.ValueToInt(woreid, 0)
		pm.Operatetime = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
		pm.Credatuz = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
		pm.Lastmodif = utils.TimeFormat(time.Now(), "yyyyMMddHHmmss")
		pm.Lastuser = t.Lastuser
		err = pm.Add()
		fmt.Printf("err is :%v", err)
	}
	return nil
}

//查
func (t *PmWo) SelectOne() (PmWo, error) {
	e := db.Eloquent.Master()
	var data PmWo
	_, err := e.ID(core.PK{t.Finr, t.Maintwoid}).Get(&data)
	if err != nil {
		return data, err
	}
	var datalist []PmWoAttrlst
	err = e.Table("pm_wo_attrlst").Where("finr = ? and maintwoid = ?", t.Finr, t.Maintwoid).Find(&datalist)
	if err != nil {
		return data, err
	}
	data.Valst = datalist
	return data, nil
}

//查
func (t *PmWo) SelectPmWoOne() (PmWo, error) {
	e := db.Eloquent.Master()
	var data PmWo
	_, err := e.Where("finr = ? and mainservicenr = ? and assetid = ?", t.Finr, t.Mainservicenr, t.Assetid).OrderBy("schedbegtime desc").Get(&data)
	if err != nil {
		return data, err
	}
	return data, nil
}

type PmWoDate struct {
	Date    string        `json:"date"`
	Content []PmWoContent `json:"content"`
}
type PmWoContent struct {
	Key    string `json:"key"`
	Value  string `json:"value"`
	Status int    `json:"status"`
}

//按月份查询维护工单调度
func (t *PmWo) SelectPmWoAll(nowdate string) ([]PmWoDate, error) {
	e := db.Eloquent.Master()
	data := make([]PmWo, 0)
	datalist := make([]PmWoDate, 0)
	temlist := make(map[string][]PmWoContent)
	query := e.Table("pm_wo").Where("finr = ?", t.Finr)
	if !utils.ValueIsEmpty(nowdate) {
		time1, _ := utils.TimeParseyyyyMMdd(nowdate)
		first, last := utils.TimeReturnMonth(time1)
		query = query.And("plbegdat >= ?", first)
		query = query.And("plbegdat <= ?", last)
	} else {
		first, last := utils.TimeReturnMonth(time.Now())
		query = query.And("plbegdat >= ?", first)
		query = query.And("plbegdat <= ?", last)
	}
	if t.Status > 0 {
		query = query.And("status = ?", t.Status)
	}
	if t.Assetid > 0 {
		query = query.And("assetid = ?", t.Assetid)
	}
	err := query.Find(&data)
	if err != nil {
		return datalist, err
	}
	for _, v := range data {
		str := v.Plbegdat
		key := str[0:4] + "-" + str[4:6] + "-" + str[6:8]
		content := PmWoContent{}
		content.Key = v.Mainservicenr
		content.Value = v.Descr
		content.Status = v.Status
		temlist[key] = append(temlist[key], content)
	}

	for key, content := range temlist {
		dataone := PmWoDate{}
		dataone.Date = key
		dataone.Content = content
		datalist = append(datalist, dataone)
	}
	return datalist, nil
}

//分页
func (t *PmWo) GetPage(pageSize int, pageIndex int, searchtime string, mainttype string, userId string) ([]PmWoService, int, error) {
	data := make([]PmWoService, 0)

	e := db.Eloquent.Master()
	assetIdLi := make([]int, 0)
	err := e.Table("PM_UserAssetLst").Where("UserId = ?", userId).Cols("AssetId").Find(&assetIdLi)
	if err != nil {
		return data, 0, err
	}
	serviceIdLi := make([]int, 0)
	err = e.Table("PM_UserServiceLst").Where("UserId = ?", userId).Cols("MainServiceId").Find(&serviceIdLi)
	if err != nil {
		return data, 0, err
	}
	where := `from pm_wo left join pm_service on pm_wo.finr = pm_service.finr and pm_wo.mainservicenr = pm_service.mainserviceid`
	where += " where pm_wo.finr = ? "
	parameters := []interface{}{t.Finr}
	table := e.Table(t.TableName()).Where("pm_wo.finr = ? ", t.Finr)
	query := e.Table(t.TableName())
	table = table.Join("LEFT", "pm_service", "pm_wo.finr = pm_service.finr and pm_wo.mainservicenr = pm_service.mainserviceid")

	if !utils.ValueIsEmpty(searchtime) {
		searchtimes := strings.Split(searchtime, "-")
		table = table.And("pm_wo.actbegtime >= ?", searchtimes[0])
		table = table.And("pm_wo.actbegtime <= ?", searchtimes[1])
		where += " and pm_wo.actbegtime >= ? "
		where += " and pm_wo.actbegtime <= ? "
		parameters = append(parameters, searchtimes[0], searchtimes[1])
	}
	if t.Assetid > 0 {
		table = table.And("pm_wo.assetid = ?", t.Assetid)
		where += " and pm_wo.assetid = ? "
		parameters = append(parameters, t.Assetid)
	}
	if t.Status == 80 {
		table = table.And("pm_wo.status = 80")
		where += " and pm_wo.status = 80 "

	} else {
		statusLi := []int{26, 40}
		table = table.In("pm_wo.status", statusLi)
		where += " and pm_wo.status in (26, 40) "
	}
	if mainttype != "" {
		table = table.Where("pm_wo.mainttype = ?", mainttype)
		where += " and pm_wo.mainttype = ? "
		parameters = append(parameters, mainttype)
	}
	table = table.In("pm_wo.assetid", assetIdLi)
	table = table.In("pm_wo.mainservicenr", serviceIdLi)
	if len(assetIdLi) > 0 {
		inAssetStr := "("
		for index, assetId := range assetIdLi {
			inAssetStr += strconv.Itoa(assetId)
			if index != len(assetIdLi)-1 {
				inAssetStr += ","
			}
		}
		inAssetStr += ")"
		where = where + " and pm_wo.assetid in " + inAssetStr + " "
	} else {
		where += " and 1 = 2 "
	}
	if len(serviceIdLi) > 0 {
		inServiceStr := "("
		for index, serviceId := range serviceIdLi {
			inServiceStr += strconv.Itoa(serviceId)
			if index != len(serviceIdLi)-1 {
				inServiceStr += ","
			}
		}
		inServiceStr += ")"
		where = where + " and pm_wo.mainservicenr in " + inServiceStr + " "
	} else {
		where += " and 1 = 2 "
	}

	orderBy := " order by pm_wo.finr "
	offset := (pageIndex - 1) * pageSize
	querySql := `select pm_wo.*,pm_service.* ` + where + orderBy + " offset ? row fetch next ? row only"
	parameters = append(parameters, offset, pageSize)
	err = query.SQL(querySql, parameters...).Find(&data)
	if err != nil {
		fmt.Println("err:", err)
		return data, 0, err
	}

	pcount := new(PmWoService)
	count, err := table.Count(pcount)
	if err != nil {
		fmt.Println("err2:", err)
		return data, 0, err
	}
	now := time.Now()
	for index, item := range data {
		closeTimeStr := item.Schedendtime
		closeTime, err := time.ParseInLocation("20060102150405", closeTimeStr, utils.TimezoneLocation)
		if err != nil {
			continue
		}
		if now.Before(closeTime) {
			item.UrgencyDegree = UngencyStatusNot
		} else {
			item.UrgencyDegree = UngencyStatusYes
		}
		data[index] = item
	}
	return data, int(count), nil
}

//分页
func (t *PmWo) GetMonthPage(pageSize int, pageIndex int, nowdate string) ([]PmWo, int, error) {
	data := make([]PmWo, 0)
	e := db.Eloquent.Master()
	table := e.Table("pm_wo").Where("finr = ? ", t.Finr)
	where := "where finr = " + "'" + utils.ValueToString(t.Finr, "") + "'"

	if !utils.ValueIsEmpty(nowdate) {
		time1, _ := utils.TimeParseyyyyMMdd(nowdate)
		first, last := utils.TimeReturnMonth(time1)
		table = table.And("plbegdat >= ?", first)
		table = table.And("plbegdat <= ?", last)
		where += " and plbegdat >= " + "'" + utils.ValueToString(first, "") + "'"
		where += " and plbegdat <= " + "'" + utils.ValueToString(last, "") + "'"
	} else {
		first, last := utils.TimeReturnMonth(time.Now())
		table = table.And("plbegdat >= ?", first)
		table = table.And("plbegdat <= ?", last)
		where += " and plbegdat >= " + "'" + utils.ValueToString(first, "") + "'"
		where += " and plbegdat <= " + "'" + utils.ValueToString(last, "") + "'"
	}
	if t.Assetid > 0 {
		table = table.And("assetid = ?", t.Assetid)
		where += " and assetid = " + "'" + utils.ValueToString(t.Assetid, "") + "'"
	}
	if t.Status > 0 {
		table = table.And("status = ?", t.Status)
		where += " and status = " + "'" + utils.ValueToString(t.Status, "") + "'"
	}

	Offset := (pageIndex - 1) * pageSize
	err := e.SQL("SELECT TOP " + utils.ValueToString(pageSize, "") + " pm_wo.* FROM pm_wo " + where + " AND (convert(varchar(10),finr)+convert(varchar(40),maintwoid) NOT IN (SELECT TOP " + utils.ValueToString(Offset, "") + " convert(varchar(10),finr)+convert(varchar(40),maintwoid) FROM pm_wo " + where + " ORDER BY credatuz DESC)) ORDER BY credatuz DESC").Find(&data)
	pcount := new(PmWo)
	count, err := table.Count(pcount)
	if err != nil {
		return data, 0, err
	}
	return data, int(count), nil
}

type CreateData struct {
	TaskType             string
	PmAsset              `xorm:"extends"`
	PmAssetTemplatelst   `xorm:"extends"`
	PmTemplate           `xorm:"extends"`
	PmTemplateServicelst `xorm:"extends"`
	PmService            `xorm:"extends"`
}


