//go:build windows
// +build windows

package comm

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"os"
	"path"
	"time"

	"github.com/nats-io/nats.go"
)

var msgbus *NatsBus

// 开启liscense检测
func InitLiscenseBus(bus *NatsBus) error {
	msgbus = bus

	// liscense = NewLiscenseTask()
	// return liscense.Run(nil)

	return nil
}

type LiscenseTask struct {
	Task

	time.Time

	dirty bool

	SK string

	activeObj     *LiscenseActiveCode
	appPrivateKey []byte
	appKey        string
	keyLabel      []byte
	DataDir       string
}

type TimeFlag struct {
	I  string
	R  int32
	LT time.Time
}

func NewLiscenseTask(sk string, privateKey string, label string, appKey string, dataDir string) *LiscenseTask {
	t := &LiscenseTask{SK: sk, appPrivateKey: []byte(privateKey), keyLabel: []byte(label), appKey: appKey, DataDir: dataDir}
	t.Task = NewBackgroundTask(t, nil)
	t.LoadLiscense()

	t.SubscribeActiveMsg()

	return t
}

type ActiveReq struct {
	ActiveCode string
}
type ActiveResp struct {
	Error      error
	Succ       bool
	AuthName   string
	StartTime  time.Time
	ExpireTime time.Time
	Duration   int
	ErrorDesc  string
}

// 加本地liscense
func (t *LiscenseTask) LoadLiscense() error {
	datafile := path.Join(t.DataDir, "liscense")
	d, e := ioutil.ReadFile(datafile)
	if e != nil {
		return e
	}

	c, e := base64.StdEncoding.DecodeString(string(d))
	if e != nil {
		return e
	}

	p, e := decryptOAEP(t.appPrivateKey, c, t.keyLabel)
	if e != nil {
		return e
	}
	o := &LiscenseActiveCode{}
	e = json.Unmarshal(p, o)
	if e != nil {
		return e
	}
	t.activeObj = o
	return nil
}

func (t *LiscenseTask) Active(req *ActiveReq) *ActiveResp {
	//清除已有的激活信息
	infoPath := path.Join(t.DataDir, "authinfo")
	os.Remove(infoPath)

	//存储激活码
	datafile := path.Join(t.DataDir, "liscense")

	e := ioutil.WriteFile(datafile, []byte(req.ActiveCode), os.ModePerm)
	if e != nil {
		return &ActiveResp{Succ: false, Error: e}
	}

	e = t.LoadLiscense()
	if e != nil {
		os.Remove(datafile)
		return &ActiveResp{Succ: false, Error: fmt.Errorf("激活码无效")}
	}

	//验证当前系统时间
	if time.Now().Before(t.activeObj.CreateTime) {
		return &ActiveResp{Succ: false, Error: fmt.Errorf("系统时间无效，无法激活")}
	}

	//存储最新时间
	f := t.setTimeFlag()
	if f == nil {
		return &ActiveResp{Succ: false, Error: fmt.Errorf("系统时间无效")}
	}

	if t.IsLiscenseOk() {

		//保存激活码
		obj := t.activeObj
		ret := &ActiveResp{Succ: true, AuthName: obj.AuthName, Duration: int(obj.Duration), StartTime: obj.StartTime, ExpireTime: obj.ExpireTime}
		return ret
	}

	return &ActiveResp{Succ: false, Error: fmt.Errorf("激活码无效")}
}

func (t *LiscenseTask) UpdateAuthInfo(status string) {
	info := &AuthInfo{}
	info.AuthId = t.activeObj.AuthId
	info.AuthName = t.activeObj.AuthName
	info.Expired = t.activeObj.ExpireTime
	info.CreateTime = t.activeObj.CreateTime
	info.Duration = t.activeObj.Duration
	info.Status = status

	infoPath := path.Join(t.DataDir, "authinfo")
	d, e := json.Marshal(info)
	if e == nil {
		ioutil.WriteFile(infoPath, d, os.ModePerm)
	}
}

func (t *LiscenseTask) SubscribeActiveMsg() {
	if msgbus == nil {
		return
	}

	msgbus.QueueSubscribe(&SubOption{
		Sub: "liscense.active." + t.appKey,
		Obj: func() interface{} { return &ActiveReq{} },
		Call: func(obj interface{}, msg *nats.Msg) interface{} {
			req := obj.(*ActiveReq)
			resp := t.Active(req)
			if resp.Error != nil {
				resp.ErrorDesc = resp.Error.Error()
			} else {
				msgbus.PublishObj("liscense.active.succ", map[string]string{"appkey": t.appKey})
			}
			return resp
		},
	})
}

func (t *LiscenseTask) getTimeFlag() *TimeFlag {
	//存储最新时间
	tickfile := path.Join(t.DataDir, "tick")
	d, e := ioutil.ReadFile(tickfile)
	if e != nil {
		return nil
	}
	p, e := Decode(t.SK, string(d))
	if e != nil {
		return nil
	}
	f := &TimeFlag{}
	e = json.Unmarshal(p, f)
	if e != nil {
		return nil
	}
	if f.I != t.appKey {
		return nil
	}
	return f
}

func (t *LiscenseTask) setTimeFlag() *TimeFlag {
	//存储最新时间
	tickfile := path.Join(t.DataDir, "tick")
	f := &TimeFlag{I: t.appKey, R: radomInt(), LT: time.Now()}
	flag, e := json.Marshal(f)
	if e != nil {
		return nil
	}
	c, e := Encode(t.SK, flag)

	if e != nil {
		return nil
	}
	e = ioutil.WriteFile(tickfile, []byte(c), os.ModePerm)
	if e != nil {
		return nil
	}
	return f
}

func (t *LiscenseTask) UpdateTimeFlag() bool {
	f1 := t.getTimeFlag()
	if f1 == nil {
		t.dirty = true
		return false
	}
	if time.Now().Before(f1.LT) {
		t.dirty = true
		return false
	}
	t.dirty = false
	t.setTimeFlag()
	return true
}

func (t *LiscenseTask) IsLiscenseOk() bool {
	ready := true
	if t.activeObj == nil || t.activeObj.AppKey != t.appKey {
		ready = false
	}

	//校验系统时间
	if t.dirty {
		ready = false
	}

	if t.activeObj != nil {
		hash := GetDeviceHash()
		if t.activeObj.DeviceHashCode != hash {
			ready = false
		}
	}

	infoPath := path.Join(t.DataDir, "authinfo")
	if !ready {
		os.Remove(infoPath)
		return false
	}

	isOk := false
	s := AuthStatusNoActive
	if t.activeObj.Duration == -1 {
		isOk = true
		s = AuthStatusOK
	} else {
		n := time.Now()
		if n.Before(t.activeObj.ExpireTime) && n.After(t.activeObj.StartTime) {
			isOk = true
			s = AuthStatusOK
		} else {
			s = AuthStatusExpired
		}
		if !isOk {
			os.Remove(infoPath)
		}
	}
	t.UpdateAuthInfo(s)

	return isOk
}

func (t *LiscenseTask) Loop() bool {
	t.UpdateTimeFlag()

	time.Sleep(5 * time.Minute) //5分钟更新一下

	return false
}
func (t *LiscenseTask) OnAfterRun() error {
	return nil
}

func (t *LiscenseTask) OnBeforeRun() error {
	// if t.activeObj == nil {
	// 	return fmt.Errorf("应用未激活")
	// }
	return nil
}
