package protocol

import (
	"errors"
	"fmt"
	"strings"
	"time"
)

const (
	ReasonLevelLow    = "low"
	ReasonLevelMedium = "medium"
	ReasonLevelHigh   = "high"
)

var (
	ErrOrganizationDisabled  = errors.New("knowledge Q&A is disabled for the organization")
	ErrPolicyInvalid         = errors.New("knowledge Q&A policy is invalid")
	ErrPolicyUnavailable     = errors.New("knowledge Q&A policy is unavailable")
	ErrDataPolicyUnsupported = errors.New("knowledge Q&A data policy requirement is unsupported")
)

// OrganizationPolicy is the organization-wide Knowledge Q&A switch. A
// missing persisted row has the same product semantics as disabled.
type OrganizationPolicy struct {
	OrganizationID  string    `json:"organizationId"`
	Enabled         bool      `json:"enabled"`
	PolicyVersion   int64     `json:"policyVersion"`
	UpdatedByUserID string    `json:"updatedByUserId,omitempty"`
	CreatedAt       time.Time `json:"createdAt,omitempty"`
	UpdatedAt       time.Time `json:"updatedAt,omitempty"`
}

type OrganizationPolicyUpdate struct {
	Enabled bool `json:"enabled"`
}

type PolicyFailureCount struct {
	Code  string `json:"code"`
	Count int64  `json:"count"`
}

// PolicyMetrics is a content-free operational projection for organization
// administrators. It intentionally excludes questions, answers, evidence,
// citations, paths, and requester identities.
type PolicyMetrics struct {
	WindowDays               int64                `json:"windowDays"`
	TotalTurns               int64                `json:"totalTurns"`
	CompletedTurns           int64                `json:"completedTurns"`
	NoAnswerTurns            int64                `json:"noAnswerTurns"`
	FailedTurns              int64                `json:"failedTurns"`
	CanceledTurns            int64                `json:"canceledTurns"`
	RunningTurns             int64                `json:"runningTurns"`
	QueuedTurns              int64                `json:"queuedTurns"`
	SettledUsageTurns        int64                `json:"settledUsageTurns"`
	InputTokens              int64                `json:"inputTokens"`
	CachedInputTokens        int64                `json:"cachedInputTokens"`
	OutputTokens             int64                `json:"outputTokens"`
	FailureTypes             []PolicyFailureCount `json:"failureTypes"`
	AverageTerminalLatencyMS float64              `json:"averageTerminalLatencyMs"`
}

// EffectivePolicy is frozen into each turn snapshot. The user selects the
// hosted model and reasoning level when the session starts; the organization
// policy only decides whether the capability is enabled.
type EffectivePolicy struct {
	OrganizationID            string `json:"organizationId"`
	Model                     string `json:"model"`
	ReasonLevel               string `json:"reasonLevel"`
	OrganizationPolicyVersion int64  `json:"organizationPolicyVersion"`
	WorkloadKind              string `json:"workloadKind"`
	DataPolicyRequirementRef  string `json:"dataPolicyRequirementRef,omitempty"`
	DataPolicyProfileRef      string `json:"dataPolicyProfileRef,omitempty"`
	DataPolicyProfileVersion  string `json:"dataPolicyProfileVersion,omitempty"`
}

func NormalizeSelection(model, reasonLevel string) (string, string, error) {
	model = strings.TrimSpace(model)
	reasonLevel = strings.TrimSpace(reasonLevel)
	if model == "" {
		return "", "", policyInvalidf("hosted model is required")
	}
	switch reasonLevel {
	case ReasonLevelLow, ReasonLevelMedium, ReasonLevelHigh:
		return model, reasonLevel, nil
	default:
		return "", "", policyInvalidf("reason level must be low, medium, or high")
	}
}

func policyInvalidf(format string, args ...any) error {
	return fmt.Errorf("%w: %s", ErrPolicyInvalid, fmt.Sprintf(format, args...))
}
