package reporter

import (
	"encoding/json"
	"fmt"
	"net/url"

	"hnyfkj.com.cn/rtu/linux/utils/jsonrpc2"
)

func makeLoginReq(imei, iccid, rssi, appVersion, inheritDUI string) ([]byte, error) {
	type params struct {
		DeviceType string `json:"deviceType"`
		IMEI       string `json:"imei"`
		ICCID      string `json:"iccid"`
		RSSI       string `json:"rssi"`
		AppVersion string `json:"appVersion"`
		InheritID  string `json:"inheritDUI,omitempty"` // 继承的DUI, 可选可为空
	}

	devParams := params{
		DeviceType: "-1", // Todo: 拍照性诱智能监测设备的产品类型暂时未知 ????????
		IMEI:       imei,
		ICCID:      iccid,
		RSSI:       rssi,
		AppVersion: appVersion,
		InheritID:  inheritDUI,
	}

	req, err := jsonrpc2.BuildRequest("login", devParams)
	if err != nil {
		return nil, err
	}

	return json.Marshal(req)
}

func parseLoginResp(data []byte) (string, string, error) {
	resp, err := jsonrpc2.ParseResponse(data)
	if err != nil {
		return "", "", err
	}

	if resp.Error != nil {
		return "", "", fmt.Errorf("服务器返回错误: %d, %s", resp.Error.Code, resp.Error.Message)
	}

	var result struct {
		IMEI string `json:"imei"`
		DUI  string `json:"DUI"`
	}
	if err := json.Unmarshal(resp.Result, &result); err != nil {
		return "", "", err
	}

	if len(result.DUI) != 14 || !IsDecimal(result.DUI) {
		return "", "", fmt.Errorf("无效DUI: %q", result.DUI)
	}

	return result.IMEI, result.DUI, nil
}

func makeLogoutNotif(imei string) ([]byte, error) {
	type params struct {
		IMEI string `json:"imei"`
	}

	devParams := params{
		IMEI: imei,
	}

	msg, err := jsonrpc2.BuildNotification("logout", devParams)
	if err != nil {
		return nil, err
	}

	return json.Marshal(msg)
}

func parseUpgradeAppReq(params json.RawMessage) (serverAddr, loginUser, loginPass, remoteFile, md5value string, err error) {
	if len(params) == 0 {
		return "", "", "", "", "", fmt.Errorf("missing params")
	}

	var upgrade struct {
		URL string `json:"url"` // 升级包的URL地址
		MD5 string `json:"md5"` // 升级包的MD5校验值, 32个十六进制数字组成, 16字节
	}
	if err := json.Unmarshal(params, &upgrade); err != nil {
		return "", "", "", "", "", err
	}

	u, err := url.Parse(upgrade.URL)
	if err != nil {
		return "", "", "", "", "", fmt.Errorf("invalid URL: %s", upgrade.URL)
	}

	if u.Scheme != "ftp" {
		return "", "", "", "", "", fmt.Errorf("unsupported scheme: %s", u.Scheme)
	}

	host := u.Hostname()
	port := u.Port()
	if port == "" {
		port = "21"
	}
	serverAddr = fmt.Sprintf("%s:%s", host, port)

	loginUser = u.User.Username()
	loginPass, _ = u.User.Password()

	remoteFile = u.Path
	if remoteFile == "" {
		return "", "", "", "", "", fmt.Errorf("missing remote file path")
	}
	md5value = upgrade.MD5

	return serverAddr, loginUser, loginPass, remoteFile, md5value, nil
}

func buildResp(req *jsonrpc2.Request, result any, err error) *jsonrpc2.Response {
	if err != nil {
		return jsonrpc2.BuildError(req, -32700, err.Error())
	}

	resp, err := jsonrpc2.BuildResult(req, result)
	if err != nil {
		return jsonrpc2.BuildError(req, jsonrpc2.ErrInternal, "")
	}

	return resp
}
