package main

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

	"github.com/pingcap/crm-bot/crm"
	"github.com/pingcap/crm-bot/model"
	"github.com/pingcap/crm-bot/pkg/config"
	"github.com/pingcap/crm-bot/pkg/job"
	"github.com/pingcap/crm-bot/pkg/util"
	"github.com/pingcap/crm-bot/salesforce"
	"github.com/pingcap/crm-bot/tidbcloud"
	"github.com/pingcap/crm-bot/widetable"
)

var wbg *widetable.WidetableManager

func main() {
	config.InitConfig("config.yml", "yml", "./etc")

	wbg := widetable.NewWidetableManager()
	wbg.Start()

	wbg.Flow(walkflow)

	job.Start()
	job.AddJob("@every 4h", job.JobRunner(func() {
		wbg.Flow(walkflow)
	}))

	log.Println("Server Started")
	util.GracefulShutdown(nil, nil)
	log.Println("Server exiting")
}

func Fxxk(wbs map[string]*widetable.Widetable) {
	// todo cjl last_modified_time order
	// todo cjl cache opportunity、order name
	sources := []crm.CrmDataSource{
		{
			ApiName:           "NewOpportunityObj",
			FieldDescFileName: "./etc/business-opportunity-fielddesc.json",
			NeedFieldFileName: "./etc/business-opportunity-crm.csv",
			Topic:             "pingcap-crm-opportunity",
			Type:              reflect.TypeOf(model.PingcapCrmOpportunity{}),
			WideTableObjName:  "FxxkOpportunity",
		},
		{
			ApiName:           "SalesOrderObj",
			FieldDescFileName: "./etc/order-fielddesc.json",
			NeedFieldFileName: "./etc/order-crm.csv",
			Topic:             "pingcap-crm-order",
			Type:              reflect.TypeOf(model.PingcapCrmOrder{}),
			WideTableObjName:  "FxxkOrder",
		},
		{
			ApiName:           "PaymentObj",
			FieldDescFileName: "./etc/payment-fielddesc.json",
			NeedFieldFileName: "./etc/payment-crm.csv",
			Topic:             "pingcap-crm-payment",
			Type:              reflect.TypeOf(model.PingcapCrmPayment{}),
			WideTableObjName:  "FxxkCollection",
		},
		{
			ApiName:           "object_wr96N__c",
			FieldDescFileName: "./etc/revrec-fielddesc.json",
			NeedFieldFileName: "./etc/revrec-crm.csv",
			Topic:             "pingcap-crm-revrec",
			Url:               "https://open.fxiaoke.com/cgi/crm/custom/v2/data/query",
			Type:              reflect.TypeOf(model.PingcapCrmRevrec{}),
			WideTableObjName:  "FxxkRecrev",
			Filter: map[string]interface{}{
				"field_name":   "life_status",
				"operator":     "IN",
				"field_values": []string{"normal"},
			},
		},
	}

	for _, source := range sources {
		output := crm.CrmData(&source, source.Filter)
		log.Println("data flow ", source.Topic, len(output.Data))
		for _, wb := range wbs {
			wb.Flow(source.WideTableObjName, output.Data)
		}
	}
}

func Salesforce(wbs map[string]*widetable.Widetable) {
	tpls := []salesforce.SFTpl1{
		//{map[string]string{"q": "SELECT name, LastModifiedDate from Opportunity Order by LastModifiedDate desc"},
		//	"./etc/salesforce_opportunity.csv",
		//	salesforce.GetObejctByQuery,
		//	"pingcap-salesforce-opportunity",
		//	reflect.TypeOf(model.PingcapSalesforceOpportunity{}),
		//	"",
		//	false,
		//	map[string]string{},
		//	"SalesforceOpportunity",
		//},
		//{map[string]string{"q": "SELECT name, LastModifiedDate from Order Order by LastModifiedDate desc"},
		//	"./etc/salesforce_order.csv",
		//	salesforce.GetObejctByQuery,
		//	"pingcap-salesforce-order",
		//	reflect.TypeOf(model.PingcapSalesforceOrder{}),
		//	"",
		//	false,
		//	map[string]string{},
		//	"SalesforceOrder",
		//},
		//{
		//	map[string]string{"q": "SELECT name, LastModifiedDate from Invoice_Collection__c Order by LastModifiedDate desc"},
		//	"./etc/salesforce_collection.csv",
		//	salesforce.GetObejctByQuery,
		//	"collection",
		//	reflect.TypeOf(model.PingcapSalesforceCollection{}),
		//	"",
		//	false,
		//	map[string]string{},
		//	"SalesforceCollection",
		//},
		//{
		//	map[string]string{"q": "SELECT name, LastModifiedDate from Revenue__c Order by LastModifiedDate desc"},
		//	"./etc/salesforce_revrec.csv",
		//	salesforce.GetObejctByQuery,
		//	"revrec",
		//	reflect.TypeOf(model.PingcapSalesforceRevrec{}),
		//	"",
		//	false,
		//	map[string]string{},
		//	"SalesforceRecrev",
		//},
		{
			map[string]string{"q": "SELECT name, LastModifiedDate from Lead Order by LastModifiedDate desc limit 40"},
			"./etc/salesforce_lead.csv",
			salesforce.GetObejctByQuery,
			"lead",
			reflect.TypeOf(model.PingcapSalesforceLead{}),
			"",
			false,
			map[string]string{},
			"SalesforceLead",
		},
		{
			Object:           map[string]string{"q": "SELECT name, LastModifiedDate from Account Order by LastModifiedDate desc limit 50"},
			FilterFile:       "./etc/salesforce_account.csv",
			Fn:               salesforce.GetObejctByQuery,
			Topic:            "salesforce_account",
			Type:             reflect.TypeOf(model.CRMAccount{}),
			LastUpdateTime:   "",
			Delete:           false,
			KeyMap:           map[string]string{},
			WidetableObjName: "SalesforceAccount",
		},
	}
	defaultCmpTime := time.Now().AddDate(0, 0, -1).Format(time.RFC3339)
	for i := range tpls {
		tpl := &tpls[i]
		if tpl.LastUpdateTime == "" &&
			!tpl.Delete {
			tpl.LastUpdateTime = defaultCmpTime
		}

		data := salesforce.CrmData((*salesforce.SFTpl)(unsafe.Pointer(tpl)))
		for _, wb := range wbs {
			wb.Flow(tpl.WidetableObjName, data)
		}
	}
}

func Cloud(wbs map[string]*widetable.Widetable) {
	tidbcloudToken := tidbcloud.GetToken()
	tenants, _ := tidbcloud.LoadCloudTenant(tidbcloudToken)
	tenantsJsonBytes, _ := json.Marshal(tenants)
	tenantsMapArrData := []map[string]interface{}{}
	json.Unmarshal(tenantsJsonBytes, &tenantsMapArrData)
	for _, wb := range wbs {
		wb.Flow("ClusterTenant", tenantsMapArrData)
	}
}

func walkflow(wbs map[string]*widetable.Widetable) {
	//sfAccountTpl := salesforce.SFTpl{
	//	Object:         map[string]string{"q": "SELECT name, LastModifiedDate from Account Order by LastModifiedDate desc"},
	//	FilterFile:     "./etc/salesforce_account.csv",
	//	Fn:             salesforce.GetObejctByQuery,
	//	Topic:          "salesforce_account",
	//	Type:           nil,
	//	LastUpdateTime: "",
	//	Delete:         false,
	//}
	//ctx := context.WithValue(context.Background(), "conf", &sfAccountTpl)
	//for _, wb := range wbs {
	//	if wb.AggKey.UpdateFunc != nil {
	//		wb.AggKey.UpdateFunc(ctx, &wb.AggKey)
	//	}
	//}
	//
	//Fxxk(wbs)
	Salesforce(wbs)
	//Cloud(wbs)
}
