package statements

import (
	"errors"
	"fmt"
)

const (
	TierDedicated   = "dedicated"
	TierShared      = "shared"
	TierServerless  = "serverless"
	TierPremium     = "premium"
	TierNextGen     = "nextgen"
	TierNextGenHost = "nextgen-host"
	TierByoc        = "byoc"
	TierByocHost    = "byoc-host"
)

type ClusterHeader struct {
	Provider   *string `header:"x-provider"`
	Region     *string `header:"x-region"`
	TenantID   *uint64 `header:"x-org-id"`
	ProjectID  *uint64 `header:"x-project-id"`
	ClusterID  *string `header:"x-cluster-id"`
	DeployType *string `header:"x-deploy-type"` // "dedicated" or "shared"
}

func (h *ClusterHeader) Validate() error {
	if h.Provider == nil {
		return errors.New("provider not found")
	}
	if h.Region == nil {
		return errors.New("region not found")
	}
	if h.TenantID == nil {
		return errors.New("org id not found")
	}
	// if h.ProjectID == nil {
	// 	return errors.New("project id not found")
	// }
	if h.ClusterID == nil || *h.ClusterID == "" {
		return errors.New("cluster id not found")
	}
	if h.DeployType == nil {
		return errors.New("deploy type not found")
	}
	if !isSupportedDeployType(*h.DeployType) {
		return errors.New("deploy type must be dedicated or shared or serverless or premium or nextgen or nextgen-host or byoc or byoc-host")
	}
	return nil
}

func isSupportedDeployType(deployType string) bool {
	switch deployType {
	case TierDedicated,
		TierShared,
		TierServerless,
		TierPremium,
		TierNextGen,
		TierNextGenHost,
		TierByoc,
		TierByocHost:
		return true
	default:
		return false
	}
}

func (h *ClusterHeader) GetTenantID() string {
	if h == nil || h.TenantID == nil || *h.TenantID == 0 {
		return ""
	}
	return fmt.Sprintf("%v", *h.TenantID)
}

func (h *ClusterHeader) GetProjectID() string {
	if h == nil || h.ProjectID == nil || *h.ProjectID == 0 {
		return ""
	}
	return fmt.Sprintf("%v", *h.ProjectID)
}

func (h *ClusterHeader) GetClusterID() string {
	if h == nil || h.ClusterID == nil {
		return ""
	}
	return *h.ClusterID
}

type ListQuery struct {
	BeginTime *int     `form:"begin_time"`
	EndTime   *int     `form:"end_time"`
	Schemas   []string `form:"schemas"`
	StmtTypes []string `form:"stmt_types"`
	Text      string   `form:"text"`
	Fields    string   `form:"fields"`
}

func (q *ListQuery) Validate() error {
	if q.BeginTime == nil {
		return errors.New("begin time not found")
	}
	if q.EndTime == nil {
		return errors.New("end time not found")
	}
	if *q.BeginTime > *q.EndTime {
		return errors.New("begin time must be less than end time")
	}
	return nil
}

type PlansQuery struct {
	BeginTime  *int   `form:"begin_time"`
	EndTime    *int   `form:"end_time"`
	SchemaName string `form:"schema_name"`
	Digest     string `form:"digest"`
}

func (q *PlansQuery) Validate() error {
	if q.BeginTime == nil {
		return errors.New("begin time not found")
	}
	if q.EndTime == nil {
		return errors.New("end time not found")
	}
	if *q.BeginTime > *q.EndTime {
		return errors.New("begin time must be less than end time")
	}
	return nil
}

type DetailQuery struct {
	BeginTime  *int     `form:"begin_time"`
	EndTime    *int     `form:"end_time"`
	SchemaName string   `form:"schema_name"`
	Digest     string   `form:"digest"`
	Plans      []string `form:"plans"`
}

func (q *DetailQuery) Validate() error {
	if q.BeginTime == nil {
		return errors.New("begin time not found")
	}
	if q.EndTime == nil {
		return errors.New("end time not found")
	}
	if *q.BeginTime > *q.EndTime {
		return errors.New("begin time must be less than end time")
	}
	return nil
}
