package controllers

import (
	"errors"
	"fmt"
	"io"
	"sparrow/pkg/models"
	"sparrow/pkg/rpcs"
	"sparrow/pkg/server"
	"sparrow/services/knowoapi/services"
	"strconv"
	"time"

	"github.com/kataras/iris/v12"
)

// DeviceController api
type DeviceController struct {
	Ctx     iris.Context
	Service services.DeviceService
	Token
}

// Get 获取激活设备列表
// GET /device?pi=&ps=&proid=&device_id=
func (a *DeviceController) Get() {
	pi, err := a.Ctx.URLParamInt("pi")
	if err != nil {
		badRequest(a.Ctx, err)
		return
	}
	ps, err := a.Ctx.URLParamInt("ps")
	if err != nil {
		badRequest(a.Ctx, err)
		return
	}
	proid := a.Ctx.URLParam("proid")

	deviceid := a.Ctx.URLParam("device_id")
	vid := a.getVendorID(a.Ctx)
	datas, total, err := a.Service.GetDevices(vid, proid, pi, ps, deviceid)
	if err != nil {
		responseError(a.Ctx, ErrDatabase, err.Error())
		return
	}
	done(a.Ctx, map[string]interface{}{
		"list":  datas,
		"total": total,
	})
}

// 设备数量，包含在线数量，离线数量，总数量
// GET /devicecount
func (a *DeviceController) GetDevicecount() {
	vid := a.getVendorID(a.Ctx)
	data, err := a.Service.GetDevicesCountByVenderId(vid)

	if err != nil && err.Error() != "redigo: nil returned" {
		responseError(a.Ctx, ErrDatabase, err.Error())
		return
	}

	done(a.Ctx, data)
}

// 获取设备在线状态
// GET /devicestatus?device_id=
func (a *DeviceController) GetDevicestatus() {

	deviceid := a.Ctx.URLParam("device_id")

	var status int

	onlineargs := rpcs.ArgsGetDeviceOnlineStatus{
		Id: deviceid,
	}

	onlinereply := rpcs.ReplyGetDeviceOnlineStatus{}
	err := server.RPCCallByName(nil, rpcs.DeviceManagerName, "DeviceManager.GetDeviceOnlineStatus", onlineargs, &onlinereply)
	if err != nil && err.Error() != "redigo: nil returned" {
		server.Log.Errorf("get devie online status error: %v", err)
		responseError(a.Ctx, ErrDatabase, err.Error())
		return
	}

	if int(onlinereply.HeartbeatInterval) > 0 && len(onlinereply.ClientIP) > 0 {
		status = 1
	}

	done(a.Ctx, map[string]interface{}{
		"Status": status,
	})

}

// GetBannerdata 获取设备激活和活跃数据
// GET /bannerdata?proid=
func (a *DeviceController) GetBannerdata() {
	proid, err := a.Ctx.URLParamInt("proid")
	if err != nil {
		proid = 0
	}
	var (
		//今日激活
		tact = 0
		// 今日活跃
		tlive = 0
		// 昨日激活
		yact = 0
		// 昨日活跃
		ylive = 0
		// 累计激活
		totolact = 0
		// 环比昨日激活
		comparedWithYesterdayActive = 0.00
		//活跃占比
		rateOfTodayLive = 0.00
		//环比昨日活跃
		comparedWithYesterdayLive = 0.00
	)
	vendorid := a.getVendorID(a.Ctx)
	totolact, err = a.Service.GetDeviceCount(vendorid)
	if err != nil {
		responseError(a.Ctx, ErrDatabase, err.Error())
		return
	}
	today := time.Now().Format("2006-01-02")
	yestoday := time.Now().AddDate(0, 0, -1).Format("2006-01-02")
	tact, err = a.Service.GetActiveNumberOfDate(vendorid, today)
	if err != nil {
		responseError(a.Ctx, ErrDatabase, err.Error())
		return
	}
	tlive, err = a.Service.GetLivelyCountOfDate(vendorid, today)
	if err != nil {
		responseError(a.Ctx, ErrDatabase, err.Error())
		return
	}
	yact, err = a.Service.GetActiveNumberOfDate(vendorid, yestoday)
	if err != nil {
		responseError(a.Ctx, ErrDatabase, err.Error())
		return
	}
	ylive, err = a.Service.GetLivelyCountOfDate(vendorid, yestoday)
	if err != nil {
		responseError(a.Ctx, ErrDatabase, err.Error())
		return
	}
	if tact != 0 && yact != 0 {
		comparedWithYesterdayActive = (float64(tact) / float64(yact)) * 100
	}
	if tlive != 0 && ylive != 0 {
		comparedWithYesterdayLive = (float64(tlive) / float64(ylive)) * 100
		rateOfTodayLive = float64(tlive) / float64(totolact) * 100
	}
	//TODO 这里的productid要去掉
	result := map[string]interface{}{
		"todayAct":                    tact,
		"todayLive":                   tlive,
		"yestodayAct":                 yact,
		"yestodayLive":                ylive,
		"totalAct":                    totolact,
		"comparedWithYesterdayActive": fmt.Sprintf("%s%%", strconv.FormatFloat(comparedWithYesterdayActive, 'f', 2, 64)),
		"comparedWithYesterdayLive":   fmt.Sprintf("%s%%", strconv.FormatFloat(comparedWithYesterdayLive, 'f', 2, 64)),
		"rateOfTodayLive":             fmt.Sprintf("%s%%", strconv.FormatFloat(rateOfTodayLive, 'f', 2, 64)),
		"productid":                   proid,
	}
	done(a.Ctx, result)
}

// GetActivechart 获取N日的激活数据趋势
func (a *DeviceController) GetActivechart() {
	// proid, err := a.Ctx.URLParamInt("proid")
	// if err != nil {
	// 	proid = 0
	// }
	days, err := a.Ctx.URLParamInt("days")
	if err != nil {
		days = 7
	}
	if days > 30 {
		badRequest(a.Ctx, errors.New("非法参数"))
		return
	}
	vendorid := a.getVendorID(a.Ctx)
	datas, err := a.Service.GetActiveOfNumDays(vendorid, days)
	if err != nil {
		responseError(a.Ctx, ErrDatabase, err.Error())
		return
	}
	done(a.Ctx, map[string]interface{}{
		"chart": datas,
	})
}

// GetLivechart 获取N日内的活跃数据
func (a *DeviceController) GetLivechart() {
	// proid, err := a.Ctx.URLParamInt("proid")
	// if err != nil {
	// 	proid = 0
	// }
	days, err := a.Ctx.URLParamInt("days")
	if err != nil {
		days = 7
	}
	if days > 30 {
		badRequest(a.Ctx, errors.New("非法参数"))
		return
	}
	vendorid := a.getVendorID(a.Ctx)
	datas, err := a.Service.GetLivelyOfNumDays(vendorid, days)
	if err != nil {
		responseError(a.Ctx, ErrDatabase, err.Error())
		return
	}
	done(a.Ctx, map[string]interface{}{
		"chart": datas,
	})
}

// PostOtaUpgrade ota升级
// POST /device/ota/upgrade
func (a *DeviceController) PostOtaUpgrade() {
	params := new(models.UpgradeParams)
	params.DeviceID = a.Ctx.FormValue("device_id")
	params.VendorID = a.Token.getVendorID(a.Ctx)
	file, header, err := a.Ctx.FormFile("file")
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	fileBytes, err := io.ReadAll(file)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	params.FileSize = header.Size
	params.File = fileBytes
	params.FileName = header.Filename
	err = a.Service.Upgrade(params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params)
}

// GetOtaProgress ota升级
// GET /device/ota/progress?device_id=
func (a *DeviceController) GetOtaProgress() {
	deviceId := a.Ctx.URLParam("device_id")

	data, err := a.Service.GetUpgradeProgress(deviceId)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, map[string]interface{}{
		"progress": data.Progress,
	})
}

// GetStatus 获取设备信息
// GET /device/status?device_id=&product_id=
func (a *DeviceController) GetStatus() {
	deviceId := a.Ctx.URLParam("device_id")
	productId := a.Ctx.URLParam("product_id")
	data, err := a.Service.GetDeviceStatus(deviceId, productId)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, map[string]interface{}{
		"data": data.MustToJsonString(),
	})
}

// GetEvent 获取设备事件信息
// GET /device/event?device_id=&product_id=
func (a *DeviceController) GetEvent() {
	deviceId := a.Ctx.URLParam("device_id")
	productId := a.Ctx.URLParam("product_id")
	data, err := a.Service.GetDeviceEvent(deviceId, productId)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, map[string]interface{}{
		"data": data.MustToJsonString(),
	})
}

// PostReport  获取设备状态
// POST /device/report
func (a *DeviceController) PostReport() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	result, err := a.Service.SetReport(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, result)
}

// PostRestart 重启设备
// POST /device/restart
func (a *DeviceController) PostRestart() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	err := a.Service.Restart(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params.DeviceId)
}

// PostClear 清除设备配置数据
// POST /device/clear
func (a *DeviceController) PostClear() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	err := a.Service.ClearData(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params.DeviceId)
}

// PostDatatrans 设备端自动上报配置
// POST /device/datarrans
func (a *DeviceController) PostDatatrans() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	err := a.Service.SetDataTrans(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params.DeviceId)
}

// PostInfo
// POST /device/info
func (a *DeviceController) PostInfo() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	result, err := a.Service.GetInfo(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, result)
}

// PostForcerun 远程控制某个模块强制运行
// POST /device/forcerun
func (a *DeviceController) PostForcerun() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	err := a.Service.ForceRun(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params.DeviceId)
}

// PostId  写入设备 ID
// POST /device/id
func (a *DeviceController) PostId() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	err := a.Service.SetDeviceId(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params.DeviceId)
}

// PostFjsq 智能分集水器控制
// POST /device/fjsq
func (a *DeviceController) PostFjsq() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	err := a.Service.SetFjsqStatus(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params.DeviceId)
}

// PostOutdoorpower 设置水系统外机电源状态
// POST /device/outdoorpower
func (a *DeviceController) PostOutdoorpower() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	err := a.Service.SetOutdoorPower(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params.DeviceId)
}

// PostOutdoortemp 设置水系统外机出水温度
// POST /device/outdoortemp
func (a *DeviceController) PostOutdoortemp() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	err := a.Service.SetOutdoorTemp(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params.DeviceId)
}

// PostOutdoorlinkage 开启/关闭水系统联动
// POST /device/outdoorlinkage
func (a *DeviceController) PostOutdoorlinkage() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	err := a.Service.SetOutdoorLinkage(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params.DeviceId)
}

// PostMixedwaterlinkage 开启/关闭调温中心联动
// POST /device/mixedwaterlinkage
func (a *DeviceController) PostMixedwaterlinkage() {
	params := new(models.SendSplitCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	err := a.Service.SetMixedWaterLinkage(*params)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params.DeviceId)
}

// Put 更新
// PUT /device
func (a *DeviceController) Put() {
	params := new(models.Device)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}
	if err := a.Service.Update(params); err != nil {
		responseError(a.Ctx, ErrDatabase, err.Error())
		return
	}
	done(a.Ctx, "已保存")
}

// PostSendcommand 下发指令
// POST /device/sendcommand
func (a *DeviceController) PostSendcommand() {
	params := new(models.SendCommandParams)
	if err := parseBody(a.Ctx, params); err != nil {
		badRequest(a.Ctx, err)
		return
	}

	err := a.Service.SendCommand(rpcs.ArgsSendCommand{
		DeviceId:  params.DeviceId,
		SubDevice: params.SunDeviceId,
		Cmd:       params.Cmd,
		Params:    params.Params,
	})

	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, params.DeviceId)
}

// GetScene 获取场景
// GET /device/scene?code=&pi=&ps=
func (a *DeviceController) GetScene() {
	pi, err := a.Ctx.URLParamInt("pi")
	if err != nil {
		badRequest(a.Ctx, err)
		return
	}
	ps, err := a.Ctx.URLParamInt("ps")
	if err != nil {
		badRequest(a.Ctx, err)
		return
	}
	code := a.Ctx.URLParam("code")
	datas, total, err := a.Service.GetScenes(code, pi, ps)
	if err != nil {
		responseError(a.Ctx, ErrNormal, err.Error())
		return
	}
	done(a.Ctx, map[string]interface{}{
		"list":  datas,
		"total": total,
	})
}
