package seller

import (
	"Wine-Server/utils"
	"Wine-Server/utils/tables"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

func VersionHandler(ctx *gin.Context) {
	version := tables.VersionTable{}
	err := version.GetLatest()
	if err != nil {
		ctx.JSON(utils.HttpError, utils.Fail("Get latest version failed"))
		return
	}
	ctx.JSON(utils.HttpOk, utils.Success(version))
}

func infoOfDevice(device *tables.DeviceTable, conn *websocket.Conn) {
	_ = conn.WriteJSON(utils.WsEvent("locationResult", utils.JsonType{
		"val": device.Addr, "close": false,
	}))

	var err error
	for i := 0; i < 4; i++ {
		err = device.Wines[i].Get()
		if err != nil {
			_ = conn.WriteJSON(utils.WsError("Query wine info failed"))
			return
		}
	}
	_ = conn.WriteJSON(utils.WsEvent("wineResult", device.Wines))

	var advList []tables.AdvertiseTable
	advList, err = tables.AdvListAll()
	if err != nil {
		_ = conn.WriteJSON(utils.WsError("Query advertise failed"))
		return
	}
	_ = conn.WriteJSON(utils.WsEvent("advResult", advList))

	var runParams []tables.ParamsTable
	runParams, err = tables.ParamsListAll()
	if err != nil {
		_ = conn.WriteJSON(utils.WsError("Query running params failed"))
		return
	}
	_ = conn.WriteJSON(utils.WsEvent("runParamResult", runParams))
	_ = conn.WriteJSON(utils.WsEvent("initFinish", nil))
}

func updateLocation(device *tables.DeviceTable, conn *websocket.Conn, data any) {
	if data == "" {
		_ = conn.WriteJSON(utils.WsError("Blank address is not allowed"))
		return
	}
	if device.Addr != data {
		err := device.Update(utils.JsonType{"addr": data})
		if err != nil {
			_ = conn.WriteJSON(utils.WsError("Update location failed"))
			return
		}
		_ = conn.WriteJSON(utils.WsEvent("locationResult", utils.JsonType{
			"val": data, "close": true,
		}))
		return
	}
	_ = conn.WriteJSON(utils.WsError("same location"))
}

type wineParam struct {
	Id     uint16 `json:"id"`
	Weight int    `json:"weight"`
}

func getQrcode(conn *websocket.Conn, data any) {
	var list []wineParam
	err := utils.AnyTrans(data, &list)
	if err != nil {
		_ = conn.WriteJSON(utils.WsError("param error"))
		return
	}
	sum := 0
	for _, item := range list {
		wine := tables.WineTable{Id: item.Id}
		err = wine.Get()
		if err != nil {
			_ = conn.WriteJSON(utils.WsError(fmt.Sprintf("no such wine: %d", item.Id)))
			return
		}
		sum += item.Weight * int(wine.Price)
	}
	fmt.Println(sum)
	_ = conn.WriteJSON(utils.WsEvent("qrcodeOkayed", "/seller/icon/qrcode.svg"))
}

type authParam struct {
	Type string `json:"type"`
	Wid  string `json:"wid"`
	Code string `json:"code"`
}

func checkAuthCode(conn *websocket.Conn, did string, data any) {
	var param authParam
	err := utils.AnyTrans(data, &param)
	if err != nil {
		_ = conn.WriteJSON(utils.WsError("params error"))
		return
	}
	fmt.Printf("checkAuthCode: device[%s], code[%s]\n", did, data)
	switch param.Type {
	case "Changing":
		// TODO: check redis `Change_${did}_${param.wid}` === param.code, query real work
		_ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
			"type": param.Type, "ok": true, "work": []utils.JsonType{
				{
					"cell": 1,
					"old": utils.JsonType{"id": 13026, "name": "某一款酒名-1", "remain": 300},
					"new": utils.JsonType{"id": 13026, "name": "某一款酒名-1", "remain": 15000},
				},
				{
					"cell": 2,
					"old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
					"new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
				},
				{
					"cell": 3,
					"old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
					"new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
				},
				{
					"cell": 4,
					"old": utils.JsonType{"id": 13027, "name": "某一款酒名-2", "remain": 286},
					"new": utils.JsonType{"id": 13029, "name": "某一款酒名-3", "remain": 15000},
				},
			},
		}))
		break
	case "Fixing":
		// TODO: check redis `Fix_${did}_${param.wid}` === param.code
		_ = conn.WriteJSON(utils.WsEvent("authCodeResult", utils.JsonType{
			"type": param.Type, "ok": true,
		}))
		break
	default:
		_ = conn.WriteJSON(utils.WsError("unrecognized open type"))
	}
}

type resultParam struct {
	Type   string `json:"type"`
	Wid    string `json:"wid"`
	Result bool   `json:"result"`
}

func openResult(conn *websocket.Conn, data any) {
	var param resultParam
	err := utils.AnyTrans(data, &param)
	if err != nil {
		_ = conn.WriteJSON(utils.WsError("params error"))
		return
	}
	if worker, win := utils.WorkerWss[param.Wid]; win {
		_ = worker.WriteJSON(utils.WsEvent("openResult", utils.JsonType{
			"type": param.Type, "result": param.Result,
		}))
		return
	}
	_ = conn.WriteJSON(utils.WsError("no such worker"))
}

type finishParam struct {
	Type string `json:"type"`
	Wid  string `json:"wid"`
}

func workFinished(conn *websocket.Conn, data any) {
	var param finishParam
	err := utils.AnyTrans(data, &param)
	if err != nil {
		_ = conn.WriteJSON(utils.WsError("params error"))
		return
	}
	if worker, win := utils.WorkerWss[param.Wid]; win {
		_ = worker.WriteJSON(utils.WsEvent("workFinished", param.Type))
	} else {
		_ = conn.WriteJSON(utils.WsError("no such worker"))
	}
}
