package processor

import (
	"context"
	"encoding/csv"
	"encoding/json"
	"fmt"
	"log"
	"os"
	"path/filepath"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/aws/aws-sdk-go-v2/config"
	"github.com/tidbcloud/observability/data-collector/pkg/common"
)

type DataProcessor struct {
	cli S3Client
}

func NewDataProcessor(region string) *DataProcessor {
	cfg, err := InitAWSConfig(region)
	if err != nil {
		return nil
	}
	cli := NewS3Client(cfg)
	return &DataProcessor{
		cli: cli,
	}
}

func InitAWSConfig(region string) (aws.Config, error) {
	if len(region) == 0 {
		return aws.Config{}, fmt.Errorf("region is empty")
	}
	cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region))
	if err != nil {
		log.Printf("failed to create session, err: %s", err.Error())
	}

	return cfg, err
}

func SaveCheckPoint(fileName string, ts int64) {
	cp := common.CheckPoint{
		Timestamp: ts,
	}
	WriteJsonFile(fileName, cp)
}

func SaveClusterIDMap(fileName string, mp map[string]map[string]bool) {
	cp := common.ClusterIDMap{
		ClusterID: mp,
	}
	WriteJsonFile(fileName, cp)
}

func WriteJsonFile(fn string, data interface{}) {
	file, err := os.OpenFile(fn, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, os.ModePerm)
	if err != nil {
		return
	}
	defer file.Close()
	encoder := json.NewEncoder(file)
	err = encoder.Encode(data)
	if err != nil {
		log.Printf("write json file failed, err %s", err.Error())
	}
}

func GetCheckPoint(fileName string) (cp *common.CheckPoint, err error) {
	if _, err = os.Stat(fileName); os.IsNotExist(err) {
		return nil, err
	}
	file, err := os.Open(fileName)
	if err != nil {
		return
	}
	defer file.Close()
	decoder := json.NewDecoder(file)
	err = decoder.Decode(&cp)

	return
}

func GetClusterIDMap(fileName string) (mp *common.ClusterIDMap, err error) {
	if _, err = os.Stat(fileName); os.IsNotExist(err) {
		return nil, err
	}
	file, err := os.Open(fileName)
	if err != nil {
		return
	}
	defer file.Close()
	decoder := json.NewDecoder(file)
	err = decoder.Decode(&mp)

	return
}

func WriteCsvFile(writer *csv.Writer, content []string) error {
	err := writer.Write(content)
	if err != nil {
		return err
	}
	writer.Flush()
	err = writer.Error()
	return err
}

var WriteCsvFileFunc = func(writer *csv.Writer, content []string) error {
	return WriteCsvFile(writer, content)
}

var DeleteFilesFunc = func(pattern string) error {
	return DeleteFiles(pattern)
}

func DeleteFiles(pattern string) error {
	files, err := filepath.Glob(pattern)
	if err != nil {
		return err
	}
	for _, f := range files {
		err = os.Remove(f)
		if err != nil {
			return err
		}
	}
	return nil
}
