package models

import (
	"bytes"
	"fmt"
	"time"

	"lc/common/util"
)

type EventType int

const (
	ET_ONLINE  EventType = 1 //上线
	ET_OFFLINE EventType = 2 //下线
	ET_ONLAMP  EventType = 3 //开灯
	ET_OFFLAMP EventType = 4 //关灯
)

type DeviceEvents struct {
	ID        uint      `gorm:"primary_key"`      //主键，自增长
	DID       string    `gorm:"type:varchar(32)"` //设备编码
	EType     EventType `gorm:"type:smallint"`    //事件类型，上线，掉线
	Time      time.Time `gorm:"type:datetime"`    //事件发生时间
	CreatedAt time.Time
}

func (DeviceEvents) TableName() string {
	return "t_device_events"
}

type DeviceLampEvents struct {
	ID         uint      `gorm:"primary_key"`                //主键，自增长
	DID        string    `gorm:"type:varchar(32)"`           //设备编码
	TStart     time.Time `gorm:"type:datetime"`              //开灯时间
	TEnd       time.Time `gorm:"type:datetime;default:null"` //关灯时间
	Brightness uint8     `gorm:"type:smallint"`              //亮度，百分比数值
	LcModel
}

func (DeviceLampEvents) TableName() string {
	return "device_lamp_events"
}

func (o DeviceLampEvents) Update() error {
	return G_db.Model(&o).Updates(DeviceLampEvents{TEnd: o.TEnd}).Error
}

func GetLampEvents(Codes []string, Start, End string) ([]DeviceLampEvents, error) {
	var array []DeviceLampEvents
	err := G_db.Model(&DeviceLampEvents{}).Where("d_id IN (?) and t_start >= ? and t_start <= ?",
		Codes, Start, End).Order("id asc").Find(&array).Error
	return array, err
}

//用于web端告警信息同步
func GetUpdateLampEvents(id uint64, update string) ([]DeviceLampEvents, error) {
	var array []DeviceLampEvents
	err := G_db.Model(&DeviceLampEvents{}).Where("id > ? OR updated_at > ?", id, update).Order("id asc").Find(&array).Error
	return array, err
}

//分割事件记录
func (o DeviceLampEvents) Split() error {
	var dle DeviceLampEvents
	err := G_db.First(&dle, o.ID).Error
	if err != nil {
		return err
	}
	create := util.MlNow()
	var arrsplit []DeviceLampEventsSplit
	if util.New(dle.TStart).BeginningOfDay() != util.New(dle.TEnd).BeginningOfDay() {
		tmpStart := dle.TStart
		for !util.New(tmpStart).BeginningOfDay().After(util.New(dle.TEnd).BeginningOfDay()) {
			tmpEnd := util.New(tmpStart).EndOfDay()
			if util.New(tmpStart).BeginningOfDay().Equal(util.New(dle.TEnd).BeginningOfDay()) {
				tmpEnd = dle.TEnd
			}
			dle := DeviceLampEventsSplit{
				OrgID:      dle.ID,
				DID:        dle.DID,
				TStart:     tmpStart,
				TEnd:       tmpEnd,
				Brightness: dle.Brightness,
				CreatedAt:  create,
			}
			arrsplit = append(arrsplit, dle)
			tmpStart = util.New(tmpStart).BeginningOfDay().AddDate(0, 0, 1)
		}
	} else {
		dle := DeviceLampEventsSplit{
			OrgID:      dle.ID,
			DID:        dle.DID,
			TStart:     dle.TStart,
			TEnd:       dle.TEnd,
			Brightness: dle.Brightness,
			CreatedAt:  create,
		}
		arrsplit = append(arrsplit, dle)
	}
	return MultiInsertDeviceLampEventsSplit(arrsplit)
}

type DeviceLampEventsSplit struct {
	ID         uint      `gorm:"primary_key"`                //主键，自增长
	OrgID      uint      `gorm:"type:bigint"`                //对应事件表ID
	DID        string    `gorm:"type:varchar(32)"`           //设备编码
	TStart     time.Time `gorm:"type:datetime"`              //开灯时间
	TEnd       time.Time `gorm:"type:datetime;default:null"` //关灯时间
	Brightness uint8     `gorm:"type:smallint"`              //亮度，百分比数值
	CreatedAt  time.Time
}

func (DeviceLampEventsSplit) TableName() string {
	return "device_lamp_events_split"
}

func MultiInsertDeviceLampEventsSplit(datas []DeviceLampEventsSplit) error {
	if len(datas) == 0 {
		return nil
	}
	var buffer bytes.Buffer
	sql := "insert into device_lamp_events_split (org_id,d_id,t_start,t_end,brightness,created_at) values"
	if _, err := buffer.WriteString(sql); err != nil {
		return err
	}
	for i, e := range datas {
		if i == len(datas)-1 {
			buffer.WriteString(fmt.Sprintf("(%d,'%s','%s','%s',%d,'%s');",
				e.OrgID, e.DID,
				e.TStart.Format("2006-01-02 15:04:05"),
				e.TEnd.Format("2006-01-02 15:04:05"),
				e.Brightness,
				e.CreatedAt.Format("2006-01-02 15:04:05")))
		} else {
			buffer.WriteString(fmt.Sprintf("(%d,'%s','%s','%s',%d,'%s'),",
				e.OrgID, e.DID,
				e.TStart.Format("2006-01-02 15:04:05"),
				e.TEnd.Format("2006-01-02 15:04:05"),
				e.Brightness,
				e.CreatedAt.Format("2006-01-02 15:04:05")))
		}
	}
	return G_db.Exec(buffer.String()).Error
}

func CalcLightingRate(t time.Time) error {
	strDate := t.Format("2006-01-02")
	return G_db.Exec("CALL CalcLightingRate(?)", strDate).Error
}

func CalcLightingMiniteRate(t time.Time) error {
	return G_db.Exec("CALL CalcLightingMiniteRate(?)", t.Format("2006-01-02 15:04:05")).Error
}

//获取已熄灯的开灯记录，对于跨日期的记录，按日期拆分
//全量处理时临时使用
func SplitDeviceLampEvents(t time.Time) error {
	var arr []DeviceLampEvents
	err := G_db.Model(DeviceLampEvents{}).Where("t_end IS NOT NULL AND DATE(t_start) = ?", t.Format("2006-01-02")).Find(&arr).Error
	if err != nil {
		return err
	}
	create := util.MlNow()
	arrsplit := make([]DeviceLampEventsSplit, 0, len(arr))
	for _, v := range arr {
		//开始日期和结束日期，不是同一日，则需要拆分
		if util.New(v.TStart).BeginningOfDay() != util.New(v.TEnd).BeginningOfDay() {
			tmpStart := v.TStart
			for !util.New(tmpStart).BeginningOfDay().After(util.New(v.TEnd).BeginningOfDay()) {
				tmpEnd := util.New(tmpStart).EndOfDay()
				if util.New(tmpStart).BeginningOfDay().Equal(util.New(v.TEnd).BeginningOfDay()) {
					tmpEnd = v.TEnd
				}
				dle := DeviceLampEventsSplit{
					OrgID:      v.ID,
					DID:        v.DID,
					TStart:     tmpStart,
					TEnd:       tmpEnd,
					Brightness: v.Brightness,
					CreatedAt:  create,
				}
				arrsplit = append(arrsplit, dle)
				tmpStart = util.New(tmpStart).BeginningOfDay().AddDate(0, 0, 1)
			}
		} else {
			dle := DeviceLampEventsSplit{
				OrgID:      v.ID,
				DID:        v.DID,
				TStart:     v.TStart,
				TEnd:       v.TEnd,
				Brightness: v.Brightness,
				CreatedAt:  create,
			}
			arrsplit = append(arrsplit, dle)
		}
	}
	return MultiInsertDeviceLampEventsSplit(arrsplit)
}
