package db

import (
	"bytes"
	"database/sql/driver"
	"encoding/json"
	"errors"
	"time"

	"github.com/BurntSushi/toml"
)

var ErrNotFound = errors.New("not found")
var ErrAlreadyExists = errors.New("already exists")

type Template struct {
	ID           int64
	TemplateName string
	Data         map[string]ConfigItem
}

type ClusterConfigFile struct {
	ClusterType  string
	ClusterID    string
	Filename     string
	TemplateID   int64
	CustomConfig map[string]ConfigItem
	Format       string
	FileText     string
}

type ConfigItem struct {
	Value   any
	Comment string
}

type anyValue struct {
	Raw any `json:"value"`
}

func NewAnyValue(v any) anyValue {
	return anyValue{v}
}

func (v *anyValue) Scan(src any) error {
	text, ok := src.([]byte)
	if !ok {
		return nil
	}

	if len(text) > 0 && text[0] == '{' {
		// compatible with old data
		return json.Unmarshal(text, &v)
	}

	return toml.Unmarshal(text, &v)
}

func (v anyValue) Value() (driver.Value, error) {
	// toml can distinguish between float and int
	output := bytes.NewBuffer(nil)
	err := toml.NewEncoder(output).Encode(v)
	return output.String(), err
}

type FileID struct {
	ClusterType string `db:"cluster_type"`
	ClusterID   string `db:"cluster_id"`
	Filename    string `db:"filename"`
}

type UniqueInstance struct {
	CloudProvider string `db:"cloud_provider"`
	NodeInstance  string `db:"instance"`
}

type ConfigurationItem struct {
	Key     string   `db:"key"`
	Value   anyValue `db:"value"`
	Comment string   `db:"comment"` // optional
}

// mysql table "templates"
type TemplateRow struct {
	ID           int64      `db:"id"`
	ClusterType  string     `db:"cluster_type"`
	Deprecated   string     `db:"filename"`
	ConfigType   string     `db:"config_type"`
	TemplateName string     `db:"template_name"`
	Tags         *string    `db:"tags"`
	ContentHash  *string    `db:"content_hash"`
	CreateTime   time.Time  `db:"create_time"`
	UpdateTime   time.Time  `db:"update_time"`
	DeleteTime   *time.Time `db:"delete_time"`
}

// mysql table "template_values"
type TemplateValueRow struct {
	ID         int64    `db:"id"`
	TemplateID int64    `db:"template_id"`
	Key        string   `db:"key"`
	Value      anyValue `db:"value"`
	Comment    string   `db:"comment"` // optional
}

// mysql table "default_templates"
type DefaultTemplateRow struct {
	ID            int64  `db:"id"`
	ClusterType   string `db:"cluster_type"`
	Deprecated    string `db:"filename"`
	ConfigType    string `db:"config_type"`
	Version       string `db:"version"`
	CloudProvider string `db:"cloud_provider"`
	NodeInstance  string `db:"instance"`
	Region        string `db:"region"`
	TenantID      string `db:"tenant_id"`
	TemplateID    int64  `db:"template_id"`
}

// mysql table "cluster_config_info"
type ClusterConfigInfoRow struct {
	ID          int64      `db:"id"`
	ClusterType string     `db:"cluster_type"`
	ClusterID   string     `db:"cluster_id"`
	Filename    string     `db:"filename"`
	ConfigType  string     `db:"config_type"`
	BelongTo    string     `db:"belong_to"`
	Format      string     `db:"format"`
	TemplateID  int64      `db:"template_id"`
	CreateTime  time.Time  `db:"create_time"`
	UpdateTime  time.Time  `db:"update_time"`
	DeleteTime  *time.Time `db:"delete_time"`
}

// mysql table "cluster_config_params"
type ClusterConfigParamRow struct {
	ID          int64  `db:"id"`
	ClusterType string `db:"cluster_type"`
	ClusterID   string `db:"cluster_id"`
	Filename    string `db:"filename"`
	ConfigurationItem
}

// mysql table "cluster_config_texts"
type ClusterConfigTextRow struct {
	ID          int64  `db:"id"`
	ClusterType string `db:"cluster_type"`
	ClusterID   string `db:"cluster_id"`
	Filename    string `db:"filename"`
	Data        string `db:"data"`
}

// mysql table "tenant_initial_custom_params"
type TenantInitialCustomParamRow struct {
	ID          int64  `db:"id"`
	ClusterType string `db:"cluster_type"`
	TenantID    uint64 `db:"tenant_id"`
	Deprecated  string `db:"filename"`
	ConfigType  string `db:"config_type"`
	ConfigurationItem
}

// mysql table "component_images"
type ComponentImageRow struct {
	ID            int64   `db:"id"`
	ClusterType   string  `db:"cluster_type"`
	ComponentName string  `db:"component_name"`
	Version       string  `db:"version"`
	BaseImage     string  `db:"base_image"`
	Tag           string  `db:"tag"`
	GA            bool    `db:"GA"`
	TenantID      *string `db:"tenant_id"`

	// Deprecated  uint64 `db:"tenant_id"`
	Deprecated2 string `db:"cluster_id"`
}

// mysql table "default_images"
type DefaultImageRow struct {
	ID            int64  `db:"id"`
	ClusterType   string `db:"cluster_type"`
	ComponentName string `db:"component_name"`
	Version       string `db:"version"`
	CloudProvider string `db:"cloud_provider"`
	BaseImage     string `db:"base_image"`
	ImageTag      string `db:"image_tag"`
}

// mysql table "cluster_components"
type ClusterComponentRow struct {
	ID                int64      `db:"id"`
	ClusterType       string     `db:"cluster_type"`
	ClusterID         string     `db:"cluster_id"`
	ComponentName     string     `db:"component_name"`
	Version           string     `db:"version"`
	CloudProvider     string     `db:"cloud_provider"`
	NodeInstance      string     `db:"instance"`
	OverwriteImageTag string     `db:"overwrite_image_tag"`
	BaseImage         string     `db:"base_image"`
	ImageTag          string     `db:"image_tag"`
	UpdateStrategy    int        `db:"update_strategy"`
	CreateTime        time.Time  `db:"create_time"`
	UpdateTime        time.Time  `db:"update_time"`
	DeleteTime        *time.Time `db:"delete_time"`
}

// mysql table "default_versions"
type DefaultVersionRow struct {
	ID             int64  `db:"id"`
	ClusterType    string `db:"cluster_type"`
	ComponentName  string `db:"component_name"`
	ClusterVersion string `db:"cluster_version"`
	CloudProvider  string `db:"cloud_provider"`
	Region         string `db:"region"`
	TenantID       uint64 `db:"tenant_id"`
	Version        string `db:"version"`
}

type AuditLogRow struct {
	ID          int64  `db:"id"`
	ClusterType string `db:"cluster_type"`
	ClusterID   string `db:"cluster_id"`
	RequestTsMs int64  `db:"request_ts_ms"`
	CommitTsMs  int64  `db:"commit_ts_ms"`
	APIName     string `db:"api_name"`
	Request     string `db:"request"`
	Response    string `db:"response"`
}

// pagination for table "default_templates"
type DefaultTemplatePager struct {
	ClusterType   string `json:"1"`
	ConfigType    string `json:"2"`
	Version       string `json:"3"`
	CloudProvider string `json:"4"`
	NodeInstance  string `json:"5"`
}

type RegionRoute struct {
	ID            int64  `db:"id"`
	ClusterType   string `db:"cluster_type"`
	LogicalRegion string `db:"logical_region"`
	Endpoint      string `db:"endpoint"`
	SyncStatus    string `db:"sync_status"`
}
