package bigquery

import (
	"encoding/json"
	"log"
	"reflect"
	"time"

	"github.com/pingcap/crm-bot/salesforce"
)

type BigQuerySFTpl struct {
	salesforce.SFTpl
	DstType     reflect.Type
	BQTableName string
}

type BigQueryDatas map[string][]interface{}

func querySalesforceData(tpls []BigQuerySFTpl, init bool) BigQueryDatas {
	datas := make(BigQueryDatas, len(tpls))
	defaultCmpTime := time.Now().AddDate(0, 0, -1).Format(time.RFC3339)
	for i := range tpls {
		tpl := &tpls[i]
		if tpl.LastUpdateTime == "" &&
			!tpl.Delete && !init {
			tpl.LastUpdateTime = defaultCmpTime
		}

		data := salesforce.CrmData(&tpl.SFTpl)
		if data == nil || len(data) == 0 {
			continue
		}

		step := 2000
		for idx := 0; idx < len(data); idx += step {
			var dataBytes []byte
			var err error

			if idx+step >= len(data) {
				dataBytes, _ = json.Marshal(data[idx:])
			} else {
				dataBytes, _ = json.Marshal(data[idx : idx+step])
			}

			if err != nil {
				log.Println("[error] json marshal ", err, tpl)
				continue
			}

			sliT := reflect.SliceOf(tpl.Type)
			SliceValue := reflect.New(sliT).Interface()
			err = json.Unmarshal(dataBytes, SliceValue)
			if err != nil {
				log.Println("[error] json unmarshal ", err, tpl)
				continue
			}
			// SliceValue is a pointer, so need Elem()
			newData := reflect.ValueOf(SliceValue).Elem().Convert(sliT).Interface()

			bqData, _ := ModelConvert(newData, tpl.DstType)
			if _, ok := datas[tpl.BQTableName]; ok {
				datas[tpl.BQTableName] = append(datas[tpl.BQTableName], bqData)
			} else {
				datas[tpl.BQTableName] = []interface{}{bqData}
			}
		}
	}

	return datas
}
