package config

import "time"

// Config is the complete application configuration loaded from config.yaml.
// It intentionally uses ordinary Go types so configuration is independent of
// protobuf generation and can be consumed by every internal module.
type Config struct {
	Server *Server `mapstructure:"server" yaml:"server" json:"server"`
	Data   *Data   `mapstructure:"data" yaml:"data" json:"data"`
	Admin  *Admin  `mapstructure:"admin" yaml:"admin" json:"admin"`
}

type Server struct {
	HTTP *ServerHTTP `mapstructure:"http" yaml:"http" json:"http"`
}

type ServerHTTP struct {
	Network string        `mapstructure:"network" yaml:"network" json:"network"`
	Addr    string        `mapstructure:"addr" yaml:"addr" json:"addr"`
	Timeout time.Duration `mapstructure:"timeout" yaml:"timeout" json:"timeout"`
}

type Data struct {
	Database     *Database   `mapstructure:"database" yaml:"database" json:"database"`
	Redis        *Redis      `mapstructure:"redis" yaml:"redis" json:"redis"`
	DatabaseList []*Database `mapstructure:"database_list" yaml:"database_list" json:"database_list"`
	RedisList    []*Redis    `mapstructure:"redis_list" yaml:"redis_list" json:"redis_list"`
	Mongo        *Mongo      `mapstructure:"mongo" yaml:"mongo" json:"mongo"`
}

type Database struct {
	Driver       string `mapstructure:"driver" yaml:"driver" json:"driver"`
	Source       string `mapstructure:"source" yaml:"source" json:"source"`
	Host         string `mapstructure:"host" yaml:"host" json:"host"`
	Port         string `mapstructure:"port" yaml:"port" json:"port"`
	User         string `mapstructure:"user" yaml:"user" json:"user"`
	Password     string `mapstructure:"password" yaml:"password" json:"password"`
	Name         string `mapstructure:"name" yaml:"name" json:"name"`
	Config       string `mapstructure:"config" yaml:"config" json:"config"`
	Path         string `mapstructure:"path" yaml:"path" json:"path"`
	AliasName    string `mapstructure:"alias_name" yaml:"alias_name" json:"alias_name"`
	Disable      bool   `mapstructure:"disable" yaml:"disable" json:"disable"`
	Prefix       string `mapstructure:"prefix" yaml:"prefix" json:"prefix"`
	Engine       string `mapstructure:"engine" yaml:"engine" json:"engine"`
	LogMode      string `mapstructure:"log_mode" yaml:"log_mode" json:"log_mode"`
	MaxIdleConns int    `mapstructure:"max_idle_conns" yaml:"max_idle_conns" json:"max_idle_conns"`
	MaxOpenConns int    `mapstructure:"max_open_conns" yaml:"max_open_conns" json:"max_open_conns"`
	// ConnMaxLifetime is expressed in seconds for compatibility with the
	// existing configuration contract. A bare YAML number must not mean ns.
	ConnMaxLifetime int  `mapstructure:"conn_max_lifetime" yaml:"conn_max_lifetime" json:"conn_max_lifetime"`
	Singular        bool `mapstructure:"singular" yaml:"singular" json:"singular"`
}

type Redis struct {
	Network      string        `mapstructure:"network" yaml:"network" json:"network"`
	Addr         string        `mapstructure:"addr" yaml:"addr" json:"addr"`
	ReadTimeout  time.Duration `mapstructure:"read_timeout" yaml:"read_timeout" json:"read_timeout"`
	WriteTimeout time.Duration `mapstructure:"write_timeout" yaml:"write_timeout" json:"write_timeout"`
	Name         string        `mapstructure:"name" yaml:"name" json:"name"`
	Password     string        `mapstructure:"password" yaml:"password" json:"password"`
	DB           int           `mapstructure:"db" yaml:"db" json:"db"`
	UseCluster   bool          `mapstructure:"use_cluster" yaml:"use_cluster" json:"use_cluster"`
	ClusterAddrs []string      `mapstructure:"cluster_addrs" yaml:"cluster_addrs" json:"cluster_addrs"`
}

type MongoHost struct {
	Host string `mapstructure:"host" yaml:"host" json:"host"`
	Port string `mapstructure:"port" yaml:"port" json:"port"`
}

type Mongo struct {
	Coll             string       `mapstructure:"coll" yaml:"coll" json:"coll"`
	Options          string       `mapstructure:"options" yaml:"options" json:"options"`
	Database         string       `mapstructure:"database" yaml:"database" json:"database"`
	Username         string       `mapstructure:"username" yaml:"username" json:"username"`
	Password         string       `mapstructure:"password" yaml:"password" json:"password"`
	AuthSource       string       `mapstructure:"auth_source" yaml:"auth_source" json:"auth_source"`
	MinPoolSize      uint64       `mapstructure:"min_pool_size" yaml:"min_pool_size" json:"min_pool_size"`
	MaxPoolSize      uint64       `mapstructure:"max_pool_size" yaml:"max_pool_size" json:"max_pool_size"`
	SocketTimeoutMs  int64        `mapstructure:"socket_timeout_ms" yaml:"socket_timeout_ms" json:"socket_timeout_ms"`
	ConnectTimeoutMs int64        `mapstructure:"connect_timeout_ms" yaml:"connect_timeout_ms" json:"connect_timeout_ms"`
	IsZap            bool         `mapstructure:"is_zap" yaml:"is_zap" json:"is_zap"`
	Hosts            []*MongoHost `mapstructure:"hosts" yaml:"hosts" json:"hosts"`
}

// Admin contains administration-service settings. ConfigPath is runtime
// metadata populated by the loader and never decoded from or written to YAML.
type Admin struct {
	RouterPrefix string   `mapstructure:"router_prefix" yaml:"router_prefix" json:"router_prefix"`
	JWT          *JWT     `mapstructure:"jwt" yaml:"jwt" json:"jwt"`
	Captcha      *Captcha `mapstructure:"captcha" yaml:"captcha" json:"captcha"`
	Local        *Local   `mapstructure:"local" yaml:"local" json:"local"`
	Email        *Email   `mapstructure:"email" yaml:"email" json:"email"`
	Storage      *Storage `mapstructure:"storage" yaml:"storage" json:"storage"`
	ConfigPath   string   `mapstructure:"-" yaml:"-" json:"-"`
	Media        *Media   `mapstructure:"media" yaml:"media" json:"media"`
	DiskList     []*Disk  `mapstructure:"disk_list" yaml:"disk_list" json:"disk_list"`
	System       *System  `mapstructure:"system" yaml:"system" json:"system"`
	Zap          *Zap     `mapstructure:"zap" yaml:"zap" json:"zap"`
	CORS         *CORS    `mapstructure:"cors" yaml:"cors" json:"cors"`
	App          *App     `mapstructure:"app" yaml:"app" json:"app"`
}

type JWT struct {
	SigningKey  string        `mapstructure:"signing_key" yaml:"signing_key" json:"signing_key"`
	ExpiresTime time.Duration `mapstructure:"expires_time" yaml:"expires_time" json:"expires_time"`
	BufferTime  time.Duration `mapstructure:"buffer_time" yaml:"buffer_time" json:"buffer_time"`
	Issuer      string        `mapstructure:"issuer" yaml:"issuer" json:"issuer"`
}

type Captcha struct {
	KeyLong         int           `mapstructure:"key_long" yaml:"key_long" json:"key_long"`
	ImgWidth        int           `mapstructure:"img_width" yaml:"img_width" json:"img_width"`
	ImgHeight       int           `mapstructure:"img_height" yaml:"img_height" json:"img_height"`
	StoreExpiration time.Duration `mapstructure:"store_expiration" yaml:"store_expiration" json:"store_expiration"`
}

type Local struct {
	StorePath  string `mapstructure:"store_path" yaml:"store_path" json:"store_path"`
	PathPrefix string `mapstructure:"path_prefix" yaml:"path_prefix" json:"path_prefix"`
}

type Email struct {
	To          string `mapstructure:"to" yaml:"to" json:"to"`
	From        string `mapstructure:"from" yaml:"from" json:"from"`
	Host        string `mapstructure:"host" yaml:"host" json:"host"`
	Secret      string `mapstructure:"secret" yaml:"secret" json:"secret"`
	Nickname    string `mapstructure:"nickname" yaml:"nickname" json:"nickname"`
	Port        int    `mapstructure:"port" yaml:"port" json:"port"`
	IsSSL       bool   `mapstructure:"is_ssl" yaml:"is_ssl" json:"is_ssl"`
	IsLoginAuth bool   `mapstructure:"is_login_auth" yaml:"is_login_auth" json:"is_login_auth"`
}

type Media struct {
	SessionTTL  int    `mapstructure:"session_ttl" yaml:"session_ttl" json:"session_ttl"`
	MaxFileSize int64  `mapstructure:"max_file_size" yaml:"max_file_size" json:"max_file_size"`
	ChunkDir    string `mapstructure:"chunk_dir" yaml:"chunk_dir" json:"chunk_dir"`
}

type Disk struct {
	MountPoint string `mapstructure:"mount_point" yaml:"mount_point" json:"mount_point"`
}

type System struct {
	UseRedis           bool `mapstructure:"use_redis" yaml:"use_redis" json:"use_redis"`
	UseMultipoint      bool `mapstructure:"use_multipoint" yaml:"use_multipoint" json:"use_multipoint"`
	UseStrictAuth      bool `mapstructure:"use_strict_auth" yaml:"use_strict_auth" json:"use_strict_auth"`
	DisableAutoMigrate bool `mapstructure:"disable_auto_migrate" yaml:"disable_auto_migrate" json:"disable_auto_migrate"`
	UseMongo           bool `mapstructure:"use_mongo" yaml:"use_mongo" json:"use_mongo"`
	Addr               int  `mapstructure:"addr" yaml:"addr" json:"addr"`
	IplimitCount       int  `mapstructure:"iplimit_count" yaml:"iplimit_count" json:"iplimit_count"`
	IplimitTime        int  `mapstructure:"iplimit_time" yaml:"iplimit_time" json:"iplimit_time"`
}

type Zap struct {
	Level             string   `mapstructure:"level" yaml:"level" json:"level"`
	Prefix            string   `mapstructure:"prefix" yaml:"prefix" json:"prefix"`
	Format            string   `mapstructure:"format" yaml:"format" json:"format"`
	Director          string   `mapstructure:"director" yaml:"director" json:"director"`
	EncodeLevel       string   `mapstructure:"encode_level" yaml:"encode_level" json:"encode_level"`
	StacktraceKey     string   `mapstructure:"stacktrace_key" yaml:"stacktrace_key" json:"stacktrace_key"`
	ShowLine          bool     `mapstructure:"show_line" yaml:"show_line" json:"show_line"`
	LogInConsole      bool     `mapstructure:"log_in_console" yaml:"log_in_console" json:"log_in_console"`
	RetentionDay      int      `mapstructure:"retention_day" yaml:"retention_day" json:"retention_day"`
	AccessReqBody     bool     `mapstructure:"access_req_body" yaml:"access_req_body" json:"access_req_body"`
	AccessRespData    bool     `mapstructure:"access_resp_data" yaml:"access_resp_data" json:"access_resp_data"`
	AccessReqHeaders  bool     `mapstructure:"access_req_headers" yaml:"access_req_headers" json:"access_req_headers"`
	AccessLogMaxBytes int      `mapstructure:"access_log_max_bytes" yaml:"access_log_max_bytes" json:"access_log_max_bytes"`
	FileOnlyModules   []string `mapstructure:"file_only_modules" yaml:"file_only_modules" json:"file_only_modules"`
}

type CORS struct {
	Mode      string      `mapstructure:"mode" yaml:"mode" json:"mode"`
	Whitelist []*CORSRule `mapstructure:"whitelist" yaml:"whitelist" json:"whitelist"`
}

type CORSRule struct {
	AllowOrigin      string `mapstructure:"allow_origin" yaml:"allow_origin" json:"allow_origin"`
	AllowMethods     string `mapstructure:"allow_methods" yaml:"allow_methods" json:"allow_methods"`
	AllowHeaders     string `mapstructure:"allow_headers" yaml:"allow_headers" json:"allow_headers"`
	ExposeHeaders    string `mapstructure:"expose_headers" yaml:"expose_headers" json:"expose_headers"`
	AllowCredentials bool   `mapstructure:"allow_credentials" yaml:"allow_credentials" json:"allow_credentials"`
}

type App struct {
	Node  string `mapstructure:"node" yaml:"node" json:"node"`
	AppID string `mapstructure:"app_id" yaml:"app_id" json:"app_id"`
	Env   string `mapstructure:"env" yaml:"env" json:"env"`
}

type Storage struct {
	Type         string       `mapstructure:"type" yaml:"type" json:"type"`
	Qiniu        *Qiniu       `mapstructure:"qiniu" yaml:"qiniu" json:"qiniu"`
	AliyunOSS    *ObjectStore `mapstructure:"aliyun_oss" yaml:"aliyun_oss" json:"aliyun_oss"`
	HuaweiOBS    *ObjectStore `mapstructure:"huawei_obs" yaml:"huawei_obs" json:"huawei_obs"`
	TencentCOS   *ObjectStore `mapstructure:"tencent_cos" yaml:"tencent_cos" json:"tencent_cos"`
	AWSS3        *ObjectStore `mapstructure:"aws_s3" yaml:"aws_s3" json:"aws_s3"`
	CloudflareR2 *ObjectStore `mapstructure:"cloudflare_r2" yaml:"cloudflare_r2" json:"cloudflare_r2"`
	Minio        *ObjectStore `mapstructure:"minio" yaml:"minio" json:"minio"`
}

type Qiniu struct {
	Zone          string `mapstructure:"zone" yaml:"zone" json:"zone"`
	Bucket        string `mapstructure:"bucket" yaml:"bucket" json:"bucket"`
	BaseURL       string `mapstructure:"base_url" yaml:"base_url" json:"base_url"`
	AccessKey     string `mapstructure:"access_key" yaml:"access_key" json:"access_key"`
	SecretKey     string `mapstructure:"secret_key" yaml:"secret_key" json:"secret_key"`
	UseHTTPS      bool   `mapstructure:"use_https" yaml:"use_https" json:"use_https"`
	UseCDNDomains bool   `mapstructure:"use_cdn_domains" yaml:"use_cdn_domains" json:"use_cdn_domains"`
}

type ObjectStore struct {
	Endpoint       string `mapstructure:"endpoint" yaml:"endpoint" json:"endpoint"`
	Region         string `mapstructure:"region" yaml:"region" json:"region"`
	Bucket         string `mapstructure:"bucket" yaml:"bucket" json:"bucket"`
	AccessKey      string `mapstructure:"access_key" yaml:"access_key" json:"access_key"`
	SecretKey      string `mapstructure:"secret_key" yaml:"secret_key" json:"secret_key"`
	BaseURL        string `mapstructure:"base_url" yaml:"base_url" json:"base_url"`
	PathPrefix     string `mapstructure:"path_prefix" yaml:"path_prefix" json:"path_prefix"`
	UseSSL         bool   `mapstructure:"use_ssl" yaml:"use_ssl" json:"use_ssl"`
	ForcePathStyle bool   `mapstructure:"force_path_style" yaml:"force_path_style" json:"force_path_style"`
	AccountID      string `mapstructure:"account_id" yaml:"account_id" json:"account_id"`
}
