package main

import (
	"chonho/config"
	_const "chonho/const"
	"chonho/pkg/db"
	"chonho/pkg/model"
	"chonho/util"
	"context"
	"encoding/json"
	"github.com/elastic/go-elasticsearch/v7"
	"github.com/elastic/go-elasticsearch/v7/esapi"
	"github.com/lib/pq"
	"io"
	"log"
	"strconv"
	"strings"
	"sync"
)

type Store struct {
	Id       int64 `gorm:"column=id;PRIMARY"`
	Name     string
	Phone    string
	UserId   string
	Category pq.Int64Array `gorm:"type:integer[]"`
}

type Product struct {
	Id       int64
	Name     string
	Keywords string
}

type StoreTmp struct {
	CategoryId int64
}

func main() {
	// Generate password
	// fmt.Println(sha.Decode("123456", "5e743447-3dcb-46e8-a087-a72fc4e440cc"))

	var wg sync.WaitGroup
	es, _ := elasticsearch.NewClient(elasticsearch.Config{
		Addresses: []string{
			config.ElasticSearch,
		},
	})

	db, err := db.NewDatabase(config.DbConnStr, 10, 2)
	if err != nil {
		panic("no db connection")
	}

	var stores []Store
	db.Table("stores s").
		Select("s.id, s.name, s.user_id, u.phone").
		Joins("JOIN users u on u.id = s.user_id").
		Find(&stores)
	for _, s := range stores {
		log.Printf("%v\n", s)
		keywords := s.Name + " " + s.Phone
		var products []Product
		db.Table("products AS p").
			Select("p.id, p.name, c.keywords").
			Joins("JOIN categories AS c ON c.id = p.category_id").
			Where("p.user_id = ?", s.UserId).
			Find(&products)
		for _, p := range products {
			log.Printf("   %v\n", p)
			keywords += " " + p.Name
			keywords += " " + p.Keywords
		}

		keywords = util.StripKeywords(keywords)

		var ids []int64
		var tmp []StoreTmp
		db.Raw("SELECT p.category_id FROM store_products sp JOIN products p ON p.id = sp.product_id WHERE sp.store_id = ? GROUP BY p.category_id ORDER BY p.category_id", s.Id).Scan(&tmp)
		for _, e := range tmp {
			ids = append(ids, e.CategoryId)
		}

		log.Printf("   Keywords: %s\n", keywords)
		log.Printf("   Category: %v\n", ids)

		db.Model(model.Store{
			Id: s.Id,
		}).Updates(model.Store{
			Keywords: keywords,
			Category: ids,
		})

		// push to ES
		wg.Add(1)

		go func(id int64, name string, keywords string) {
			defer wg.Done()

			str, _ := json.Marshal(map[string]interface{}{
				"name":     name,
				"keywords": keywords,
			})

			req := esapi.IndexRequest{
				Index:      _const.StoreIndex,
				DocumentID: strconv.FormatInt(id, 10),
				Body:       strings.NewReader(string(str)),
				Refresh:    "true",
			}
			res, err := req.Do(context.Background(), es)
			if err != nil {
				log.Fatalf("Error getting response: %s", err)
			}

			defer func(Body io.ReadCloser) {
				err := Body.Close()
				if err != nil {
					log.Fatalf("Error read closer: %s", err)
				}
			}(res.Body)

			if res.IsError() {
				log.Printf("[%s] Error indexing document", res.Status())
			} else {
				// Deserialize the response into a map.
				var r map[string]interface{}
				err := json.NewDecoder(res.Body).Decode(&r)
				if err != nil {
					log.Printf("Error parsing the response body: %s", err)
				} else {
					// Print the response status and indexed document version.
					log.Printf("[%s] %s; version=%d", res.Status(), r["result"], int(r["_version"].(float64)))
				}
			}
		}(s.Id, s.Name, keywords)
	}

	wg.Wait()

}
