package models

import (
	// nolint:gosec
	"crypto/md5"
	"encoding/hex"
	"strings"
	"time"

	"github.com/tidbcloud/observability/o11ymetering/pkg/common/constants"
	"gorm.io/gorm"
)

type ClusterMeta struct {
	Tenant  string `gorm:"size:32;comment:''"`
	Project string `gorm:"size:32;comment:''"`
	Cluster string `gorm:"size:64;comment:''"`
}

type StatisticRecord struct {
	ID             string                   `gorm:"primaryKey;size:32"`
	TaskID         string                   `gorm:"size:32;comment:''"`
	Region         string                   `gorm:"not null;size:32"`
	StatisticClass constants.StatisticClass `gorm:"size:32"`
	MeteringGroup  constants.MeteringGroup  `gorm:"not null;size:32;comment:''"`
	Period         string                   `gorm:"size:32;comment:'202406250800'"`
	PeriodTime     time.Time                `gorm:""`
	Env            constants.BizEnv         `gorm:"size:16;comment:''"`

	StatisticName constants.StatisticName `gorm:"not null;size:32;comment:'name of statistic'"`
	ClusterMeta
	Category    constants.Category `gorm:"size:16;comment:''"`
	SubCategory string             `gorm:"size:64;comment:''"`
	Component   string             `gorm:"size:64;comment:''"`
	Container   string             `gorm:"size:32;comment:''"`
	Source      string             `gorm:"size:16;comment:''"`
	Value       float64            `gorm:"size:64;comment:'';default:0"`
	CreatedAt   time.Time          `gorm:"autoCreateTime;<-:create;->;"`
	UpdatedAt   time.Time          `gorm:"autoUpdateTime"`
}

func (r *StatisticRecord) BeforeCreate(tx *gorm.DB) (err error) {
	if len(r.ID) == 0 {
		r.BuildID()
	}
	r.PeriodTime = Period(r.Period).StartTime()
	return nil
}

func (r *StatisticRecord) BuildID() string {
	strs := []string{
		r.Period,
		r.Region,
		string(r.Env),
		string(r.MeteringGroup),
		string(r.StatisticName),
		string(r.Category),
		r.SubCategory,
		r.ClusterMeta.Tenant,
		r.ClusterMeta.Project,
		r.ClusterMeta.Cluster,
		r.Component,
		r.Container,
		r.Source,
	}
	text := strings.Join(strs, "-")
	// nolint:gosec
	hash := md5.Sum([]byte(text))
	r.ID = hex.EncodeToString(hash[:])
	return r.ID
}

type StatisticTask struct {
	ID             string                   `gorm:"primaryKey;size:32"`
	Region         string                   `gorm:"not null;size:32"`
	StatisticClass constants.StatisticClass `gorm:"not null;size:32"`
	MeteringGroup  constants.MeteringGroup  `gorm:"not null;size:32;comment:''"`
	Period         string                   `gorm:"not null;size:32;comment:'2024-07-01 08:10:00'"`
	Env            constants.BizEnv         `gorm:"not null;size:16;comment:''"`
	State          constants.StatisticState `gorm:"size:16;comment:''"`
}

func (t *StatisticTask) BeforeCreate(tx *gorm.DB) (err error) {
	if len(t.ID) == 0 {
		t.BuildID()
	}
	return nil
}

func (t *StatisticTask) BuildID() string {
	strs := []string{
		string(t.StatisticClass),
		t.Region,
		t.Period,
		string(t.Env),
		string(t.MeteringGroup),
	}
	text := strings.Join(strs, "-")
	// nolint:gosec
	hash := md5.Sum([]byte(text))
	t.ID = hex.EncodeToString(hash[:])
	return t.ID
}
