package config

import (
	"fmt"
	"os"

	"github.com/mitchellh/mapstructure"
	"gopkg.in/yaml.v3"
)

type Config struct {
	Global  Global                   `yaml:"global"`
	Sources []map[string]interface{} `yaml:"sources"`
	Sinks   []map[string]interface{} `yaml:"sinks"`
}

func NewConfig(path string) Config {
	var config Config
	b, err := os.ReadFile(path)
	if err != nil {
		panic(fmt.Errorf("open file failed %w", err))
	}
	err = yaml.Unmarshal(b, &config)
	if err != nil {
		panic(fmt.Errorf("unmarshal yaml file failed %w", err))
	}
	return config
}

type Global struct {
	Interval int `yaml:"interval"` // Interval time minute
	Delay    int `yaml:"delay"`    //Delay time minute
}

type DBSource struct {
	Type    string `yaml:"type" mapstructure:"type"`
	Name    string `yaml:"name" mapstructure:"name"`
	DBUrl   string `yaml:"db_url" mapstructure:"db_url"`
	Version string `yaml:"version" mapstructure:"version"`
	Tables  []struct {
		Name    string    `yaml:"name" mapstructure:"name"`
		Cols    []ColType `yaml:"cols" mapstructure:"cols"`
		TimeCol string    `yaml:"time_col" mapstructure:"time_col"`
	} `yaml:"tables" mapstructure:"tables"`
}
type ColType struct {
	Name string `yaml:"name" mapstructure:"name"`
	Type string `yaml:"type" mapstructure:"type"`
}

type SourceInterface interface {
	GetType() string
	GetName() string
	GetVersion() string
}

func NewDBSource(input map[string]interface{}) DBSource {
	var dbs DBSource
	err := mapstructure.Decode(input, &dbs)
	if err != nil {
		panic(fmt.Errorf("map to struct failed %w", err))
	}
	return dbs
}

func (dbs DBSource) GetType() string {
	return dbs.Type
}

func (dbs DBSource) GetName() string {
	return dbs.Name
}
func (dbs DBSource) GetVersion() string {
	return dbs.Version
}

type S3Sink struct {
	Type       string `yaml:"type" mapstructure:"type"`
	BucketName string `yaml:"bucketName" mapstructure:"bucketName"`
	Prefix     string `yaml:"prefix" mapstructure:"prefix"`
	Region     string `yaml:"region" mapstructure:"region"`
}

func NewS3Sink(input map[string]interface{}) S3Sink {
	var s3 S3Sink
	err := mapstructure.Decode(input, &s3)
	if err != nil {
		panic(fmt.Errorf("map to struct failed %w", err))
	}
	return s3
}
