package model

import (
	"context"
	"encoding/json"
	"fmt"
	"time"
	"trading-go/common"
	"trading-go/response"
)

type Message struct {
	MsgType int  `json:"msgType"`
	From    uint `json:"from"`
	To      uint `json:"to"`
	Time    uint `json:"time"`
	Content any  `json:"content"`
}

var fromIndex map[uint]string
var toIndex map[uint]string

func init() {
	fromIndex = make(map[uint]string)
	toIndex = make(map[uint]string)
}

func (m Message) Save() error {
	rds := common.Redis
	jsonData, err := json.Marshal(m)
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()

	key := fmt.Sprintf("%d:%d:%d", m.From, m.To, m.Time)
	_, err = rds.Set(ctx, key, jsonData, time.Second*60*60*24*30).Result()
	if err != nil {
		return err
	}
	return err
}

func (m Message) GetFrom(uid uint, page, pageSize int) (ms response.PageResponse, err error) {
	var mess []Message
	if page == 1 {
		fromIndex[uid] = "0"
	}
	rds := common.Redis
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	key := fmt.Sprintf("%d:*", uid)
	result, err := rds.Do(ctx, "scan", fromIndex[uid], "match", key, "count", pageSize).Result()
	if err != nil {
		return
	}
	rs := result.([]interface{})
	index := rs[0].(string)
	if index != "0" {
		fromIndex[uid] = index
		ms.HNext = true
	}
	keys := rs[1].([]interface{})
	for i := 0; i < len(keys); i++ {
		value, err := rds.Get(ctx, keys[i].(string)).Result()
		if err != nil {
			break
		}
		err = json.Unmarshal([]byte(value), &m)
		if err != nil {
			break
		}
		mess = append(mess, m)
	}
	ms.Data = mess
	ms.PageSize = pageSize
	ms.Page = page
	return
}

func (m Message) GetTo(uid uint, page, pageSize int) (ms response.PageResponse, err error) {
	var mess []Message
	if page == 1 {
		toIndex[uid] = "0"
	}
	rds := common.Redis
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	defer cancel()
	key := fmt.Sprintf("*:%d:*", uid)
	result, err := rds.Do(ctx, "scan", toIndex[uid], "match", key, "count", pageSize).Result()
	if err != nil {
		return
	}
	rs := result.([]interface{})
	index := rs[0].(string)
	if index != "0" {
		toIndex[uid] = index
		ms.HNext = true
	}
	keys := rs[1].([]interface{})
	for i := 0; i < len(keys); i++ {
		value, err := rds.Get(ctx, keys[i].(string)).Result()
		if err != nil {
			break
		}
		err = json.Unmarshal([]byte(value), &m)
		if err != nil {
			break
		}
		mess = append(mess, m)
	}
	ms.Data = mess
	ms.PageSize = pageSize
	ms.Page = page
	return
}