package client

import (
	"github.com/juju/errors"
	"github.com/pingcap/schrodinger/pkg/elasticsearch"
)

const (
	tidbPodPrefix    = "tidb-cluster-tidb"
	pdPodPrefix      = "tidb-cluster-pd"
	tikvPodPrefix    = "tidb-cluster-tikv"
	clusterPodPrefix = "tidb-cluster"
)

func (c *Client) initLogServiceClient() error {
	c.Lock()
	defer c.Unlock()

	if c.logClient != nil {
		return nil
	}

	if c.conf.LogService == nil {
		return errors.New("the config of log service is nil")
	}

	if err := c.conf.LogService.Elastic.Validate(); err != nil {
		return errors.Trace(err)
	}

	cli, err := elasticsearch.NewClient(&c.conf.LogService.Elastic)
	if err != nil {
		return errors.Trace(err)
	}

	c.logClient = cli

	return nil
}

// FilterLog filters pods log from log service,
// returns the total number of the all hits rows and the `size` rows real log data.
// `podPrefix` parameter  defines Pods filter information
// `filterStr` parameter defines the filter string, like: "region xxx".
// `gte` parameter represents that date is greater than `gte`, like: "now-1d".
// `lte` parameter represents that date is less than `lte`, like: "now".
// `from` parameter defines the offset from the first result you want to fetch, `from` default to 0.
// `size` parameter allows you to configure the maximum amount of hits to be returned, `size` default to 10.
// Note that from + size can not be more than the index.max_result_window index setting which defaults to 10,000.
// date-match refer: https://www.elastic.co/guide/en/elasticsearch/reference/6.7/common-options.html#date-math
func (c *Client) filterLog(
	podPrefix string,
	filterStr string,
	gte string,
	lte string,
	from int,
	size int,
) (int64, []string, error) {
	if !c.isOnline() {
		Warnf("only mode online is permitted. the mode is %s", c.mode)
		return 0, nil, nil
	}

	if err := c.refreshConfig(); err != nil {
		Fatalf("init client config error %v", errors.ErrorStack(err))
	}

	if c.conf.Cat == nil {
		return 0, nil, errors.New("cat config is nil")
	}

	if len(c.conf.Cat.Namespace) == 0 {
		return 0, nil, errors.New("cat namespace is empty")
	}

	if err := c.initLogServiceClient(); err != nil {
		return 0, nil, errors.Trace(err)
	}

	total, rows, err := c.logClient.FilterLog(c.conf.Cat.Namespace, podPrefix, filterStr, gte, lte, from, size)
	if err != nil {
		return 0, nil, errors.Trace(err)
	}

	var logs []string
	for _, row := range rows {
		logs = append(logs, row.Log)
	}

	return total, logs, nil
}

// FilterTiDBLog filters tidbs log from log service,
// returns the total number of the all hits rows and the `size` rows real log data.
// `filterStr` parameter defines the filter string, like: "region xxx".
// `gte` parameter represents that date is greater than `gte`, like: "now-1d".
// `lte` parameter represents that date is less than `lte`, like: "now".
// `from` parameter defines the offset from the first result you want to fetch, `from` default to 0.
// `size` parameter allows you to configure the maximum amount of hits to be returned, `size` default to 10.
// Note that from + size can not be more than the index.max_result_window index setting which defaults to 10,000.
// date-match refer: https://www.elastic.co/guide/en/elasticsearch/reference/6.7/common-options.html#date-math
func (c *Client) FilterTiDBLog(
	filterStr string,
	gte string,
	lte string,
	from int,
	size int,
) (int64, []string, error) {
	return c.filterLog(tidbPodPrefix, filterStr, gte, lte, from, size)
}

// FilterPDLog filters pds log from log service,
// returns the total number of the all hits rows and the `size` rows real log data.
// `filterStr` parameter defines the filter string, like: "region xxx".
// `gte` parameter represents that date is greater than `gte`, like: "now-1d".
// `lte` parameter represents that date is less than `lte`, like: "now".
// `from` parameter defines the offset from the first result you want to fetch, `from` default to 0.
// `size` parameter allows you to configure the maximum amount of hits to be returned, `size` default to 10.
// Note that from + size can not be more than the index.max_result_window index setting which defaults to 10,000.
// date-match refer: https://www.elastic.co/guide/en/elasticsearch/reference/6.7/common-options.html#date-math
func (c *Client) FilterPDLog(
	filterStr string,
	gte string,
	lte string,
	from int,
	size int,
) (int64, []string, error) {
	return c.filterLog(pdPodPrefix, filterStr, gte, lte, from, size)
}

// FilterTiKVLog filters tikvs log from log service,
// returns the total number of the all hits rows and the `size` rows real log data.
// `filterStr` parameter defines the filter string, like: "region xxx".
// `gte` parameter represents that date is greater than `gte`, like: "now-1d".
// `lte` parameter represents that date is less than `lte`, like: "now".
// `from` parameter defines the offset from the first result you want to fetch, `from` default to 0.
// `size` parameter allows you to configure the maximum amount of hits to be returned, `size` default to 10.
// Note that from + size can not be more than the index.max_result_window index setting which defaults to 10,000.
// date-match refer: https://www.elastic.co/guide/en/elasticsearch/reference/6.7/common-options.html#date-math
func (c *Client) FilterTiKVLog(
	filterStr string,
	gte string,
	lte string,
	from int,
	size int,
) (int64, []string, error) {
	return c.filterLog(tikvPodPrefix, filterStr, gte, lte, from, size)
}

// FilterClusterLog filters cluster log from log service,
// returns the total number of the all hits rows and the `size` rows real log data.
// `filterStr` parameter defines the filter string, like: "region xxx".
// `gte` parameter represents that date is greater than `gte`, like: "now-1d".
// `lte` parameter represents that date is less than `lte`, like: "now".
// `from` parameter defines the offset from the first result you want to fetch, `from` default to 0.
// `size` parameter allows you to configure the maximum amount of hits to be returned, `size` default to 10.
// Note that from + size can not be more than the index.max_result_window index setting which defaults to 10,000.
// date-match refer: https://www.elastic.co/guide/en/elasticsearch/reference/6.7/common-options.html#date-math
func (c *Client) FilterClusterLog(
	filterStr string,
	gte string,
	lte string,
	from int,
	size int,
) (int64, []string, error) {
	return c.filterLog(clusterPodPrefix, filterStr, gte, lte, from, size)
}
