package framework

import (
	"context"
	"time"
)

const InputInterfaceV2IdStr InputInterfaceVersion = "InputInterfaceV2"

// TiKVUsageSnapshot captures the current disk usage state of a TiKV cluster.
type TiKVUsageSnapshot struct {
	NodeCount           uint32
	TotalCapacityBytes  uint64
	TotalAvailableBytes uint64
}

// CurrentUsageBytes returns total bytes currently in use.
func (s *TiKVUsageSnapshot) CurrentUsageBytes() uint64 {
	if s.TotalCapacityBytes <= s.TotalAvailableBytes {
		return 0
	}
	return s.TotalCapacityBytes - s.TotalAvailableBytes
}

// SingleNodeCapacityBytes returns the per-node capacity.
func (s *TiKVUsageSnapshot) SingleNodeCapacityBytes() uint64 {
	if s.NodeCount == 0 {
		return 0
	}
	return s.TotalCapacityBytes / uint64(s.NodeCount)
}

// UsagePercentage returns the current disk usage as a percentage (0-100).
func (s *TiKVUsageSnapshot) UsagePercentage() float64 {
	if s.TotalCapacityBytes == 0 {
		return 0
	}
	return float64(s.CurrentUsageBytes()) * 100 / float64(s.TotalCapacityBytes)
}

// RemainingBytes returns the total available bytes.
func (s *TiKVUsageSnapshot) RemainingBytes() uint64 {
	return s.TotalAvailableBytes
}

// NodeDiskInfo captures disk usage for a single TiKV node.
type NodeDiskInfo struct {
	Name           string
	CapacityBytes  uint64
	AvailableBytes uint64
}

// UsagePercentage returns the disk usage as a percentage (0-100).
func (n *NodeDiskInfo) UsagePercentage() float64 {
	if n.CapacityBytes == 0 {
		return 0
	}
	used := n.CapacityBytes - n.AvailableBytes
	if n.AvailableBytes > n.CapacityBytes {
		used = 0
	}
	return float64(used) * 100 / float64(n.CapacityBytes)
}

// TiKVAutoscaleFeatureFlags contains the feature flags for TiKV capacity autoscaling.
type TiKVAutoscaleFeatureFlags struct {
	EnableTikvCpuScaleOut      bool
	EnableDiskExpand           bool
	EnableIOPSThroughputExpand bool
}

// VolumeCooldownState captures whether a volume modification is in cooldown.
type VolumeCooldownState struct {
	InCooldown bool
}

// CPUDataPoint represents a single CPU utilization observation at a point in time.
type CPUDataPoint struct {
	Timestamp   time.Time
	Utilization float64
}

// DiskIOMetrics holds the current observed IOPS and throughput for a shared pool's TiKV nodes.
// DiskIOPodDevice records which block device was identified as the data disk for a pod.
type DiskIOPodDevice struct {
	PodName string // e.g. "db-ba094f7e-tikv-3bt7w7"
	Device  string // e.g. "/dev/nvme3n1"
}

type DiskIOMetrics struct {
	IOPS          float64           // current I/O operations per second (max across pods)
	ThroughputMBs float64           // current throughput in MB/s (max across pods)
	HasData       bool              // true if rate computation succeeded (needs 2+ samples)
	PerPodDevice  []DiskIOPodDevice // per-pod device identification details (diagnostic)
}

// ProvisionedDiskIO holds the provisioned IOPS and throughput for a shared pool.
type ProvisionedDiskIO struct {
	IOPS          uint32
	ThroughputMBs uint32
}

// DiskIODataPoint represents a single disk IO observation (computed rate) at a point in time.
type DiskIODataPoint struct {
	Timestamp     time.Time
	IOPS          float64 // I/O operations per second
	ThroughputMBs float64 // megabytes per second
}

// InputInterfaceV2 extends InputInterfaceV1 with typed accessors for TiKV
// capacity-based autoscaling, eliminating the need for scalers to assert
// against concrete module types.
type InputInterfaceV2 interface {
	InputInterfaceV1

	// GetRangeCPUUtilization returns cached CPU utilization data points within the given time range.
	GetRangeCPUUtilization(ctx context.Context, clusterId ClusterId, fromTo TimeRange) ([]CPUDataPoint, error)

	// GetPerNodeDiskInfo returns per-node disk usage for all TiKV nodes in the shared pool.
	GetPerNodeDiskInfo(ctx context.Context, sharedPoolID string) ([]NodeDiskInfo, error)

	// GetDiskSnapshot returns the current TiKV disk usage snapshot (aggregate).
	GetDiskSnapshot(ctx context.Context, sharedPoolID string) (*TiKVUsageSnapshot, error)

	// GetEBSCooldownState returns whether the EBS volume modification is in cooldown.
	// Returns non-nil with InCooldown=false for non-AWS providers.
	// Returns nil (no error) when the state cannot be determined (e.g. AWS without
	// DataplaneManager configured). Callers should treat nil as "unknown".
	GetEBSCooldownState(ctx context.Context, sharedPoolID string) (*VolumeCooldownState, error)

	// GetCurrentDiskSizeGB returns the current per-node TiKV disk size in GB.
	GetCurrentDiskSizeGB(ctx context.Context, sharedPoolID string) (uint32, error)

	// GetTiKVMaxNodeCount returns the current effective max TiKV node count from
	// the shared pool component quota.
	GetTiKVMaxNodeCount(ctx context.Context, sharedPoolID string) (uint32, error)

	// GetAutoscaleFeatureFlags returns the feature flags controlling REQ-4/REQ-5 autoscaling.
	GetAutoscaleFeatureFlags(ctx context.Context, sharedPoolID string) (*TiKVAutoscaleFeatureFlags, error)

	// GetDiskIOMetrics returns the current observed IOPS and throughput across TiKV pods.
	// Requires at least 2 collection cycles to have rate data; returns HasData=false otherwise.
	GetDiskIOMetrics(ctx context.Context, sharedPoolID string) (*DiskIOMetrics, error)

	// GetRangeDiskIOMetrics returns cached disk IO rate data points within the given time range.
	// Used for sustained-duration checks on IOPS/throughput (REQ-7).
	GetRangeDiskIOMetrics(ctx context.Context, sharedPoolID string, fromTo TimeRange) ([]DiskIODataPoint, error)

	// GetProvisionedDiskIO returns the provisioned IOPS and throughput from the shared pool spec.
	GetProvisionedDiskIO(ctx context.Context, sharedPoolID string) (*ProvisionedDiskIO, error)

	// GetCollectInterval returns the configured metrics collection interval.
	GetCollectInterval() time.Duration
}
