package app

import (
	"fmt"
	"strings"
	"time"

	"github.com/caarlos0/env/v11"
	webhookdomain "github.com/codex-k8s/kodex/libs/go/domain/webhook"
)

// Config defines environment-backed runtime settings for agent-runner job.
type Config struct {
	RunID                string `env:"KODEX_RUN_ID,required,notEmpty"`
	CorrelationID        string `env:"KODEX_CORRELATION_ID,required,notEmpty"`
	ProjectID            string `env:"KODEX_PROJECT_ID"`
	RepositoryFullName   string `env:"KODEX_REPOSITORY_FULL_NAME,required,notEmpty"`
	AgentKey             string `env:"KODEX_AGENT_KEY,required,notEmpty"`
	IssueNumber          int64  `env:"KODEX_ISSUE_NUMBER"`
	RunTargetBranch      string `env:"KODEX_RUN_TARGET_BRANCH"`
	ExistingPRNumber     int    `env:"KODEX_EXISTING_PR_NUMBER"`
	RuntimeMode          string `env:"KODEX_RUNTIME_MODE" envDefault:"code-only"`
	RuntimeTargetEnv     string `env:"KODEX_RUNTIME_TARGET_ENV"`
	RuntimeBuildRef      string `env:"KODEX_RUNTIME_BUILD_REF"`
	RuntimeAccessProfile string `env:"KODEX_RUNTIME_ACCESS_PROFILE"`
	// QualityGovernanceEnabled is a worker-injected snapshot of the current runtime system setting.
	QualityGovernanceEnabled bool `env:"KODEX_QUALITY_GOVERNANCE_ENABLED" envDefault:"false"`

	ControlPlaneGRPCTarget string `env:"KODEX_CONTROL_PLANE_GRPC_TARGET,required,notEmpty"`
	MCPBaseURL             string `env:"KODEX_MCP_BASE_URL,required,notEmpty"`
	MCPBearerToken         string `env:"KODEX_MCP_BEARER_TOKEN,required,notEmpty"`

	TriggerKind          string `env:"KODEX_RUN_TRIGGER_KIND" envDefault:"dev"`
	TriggerLabel         string `env:"KODEX_RUN_TRIGGER_LABEL"`
	DiscussionMode       bool   `env:"KODEX_DISCUSSION_MODE" envDefault:"false"`
	PromptTemplateKind   string `env:"KODEX_PROMPT_TEMPLATE_KIND" envDefault:"work"`
	PromptTemplateSource string `env:"KODEX_PROMPT_TEMPLATE_SOURCE" envDefault:"repo_seed"`
	PromptTemplateLocale string `env:"KODEX_PROMPT_TEMPLATE_LOCALE" envDefault:"ru"`
	StateInReviewLabel   string `env:"KODEX_STATE_IN_REVIEW_LABEL" envDefault:"state:in-review"`
	AgentModel           string `env:"KODEX_AGENT_MODEL"`
	AgentReasoningEffort string `env:"KODEX_AGENT_REASONING_EFFORT" envDefault:"high"`
	AgentBaseBranch      string `env:"KODEX_AGENT_BASE_BRANCH" envDefault:"main"`
	AgentDisplayName     string `env:"KODEX_AGENT_DISPLAY_NAME,required,notEmpty"`

	GitBotToken    string `env:"KODEX_GIT_BOT_TOKEN,required,notEmpty"`
	GitBotUsername string `env:"KODEX_GIT_BOT_USERNAME,required,notEmpty"`
	GitBotMail     string `env:"KODEX_GIT_BOT_MAIL,required,notEmpty"`
	OpenAIAPIKey   string `env:"KODEX_OPENAI_API_KEY"`

	DiscussionPollInterval time.Duration `env:"KODEX_DISCUSSION_POLL_INTERVAL" envDefault:"15s"`
}

// LoadConfig parses and validates configuration from environment.
func LoadConfig() (Config, error) {
	cfg, err := env.ParseAs[Config]()
	if err != nil {
		return Config{}, fmt.Errorf("parse agent-runner config from environment: %w", err)
	}

	cfg.TriggerKind = normalizeTriggerKind(cfg.TriggerKind)
	cfg.TriggerLabel = strings.TrimSpace(cfg.TriggerLabel)
	if cfg.TriggerLabel == "" && cfg.DiscussionMode {
		cfg.TriggerLabel = webhookdomain.DefaultModeDiscussionLabel
	}
	if cfg.TriggerLabel == "" {
		cfg.TriggerLabel = webhookdomain.DefaultTriggerLabel(webhookdomain.NormalizeTriggerKind(cfg.TriggerKind))
	}
	cfg.PromptTemplateKind = strings.TrimSpace(strings.ToLower(cfg.PromptTemplateKind))
	if cfg.DiscussionMode {
		cfg.PromptTemplateKind = promptTemplateKindDiscussion
	} else if isReviseTriggerKind(cfg.TriggerKind) {
		cfg.PromptTemplateKind = promptTemplateKindRevise
	}
	if cfg.PromptTemplateKind != promptTemplateKindRevise && cfg.PromptTemplateKind != promptTemplateKindDiscussion {
		cfg.PromptTemplateKind = promptTemplateKindWork
	}

	cfg.PromptTemplateSource = strings.TrimSpace(cfg.PromptTemplateSource)
	if cfg.PromptTemplateSource == "" {
		cfg.PromptTemplateSource = promptTemplateSourceSeed
	}
	cfg.PromptTemplateLocale = strings.TrimSpace(cfg.PromptTemplateLocale)
	if cfg.PromptTemplateLocale == "" {
		cfg.PromptTemplateLocale = "ru"
	}
	cfg.StateInReviewLabel = strings.TrimSpace(cfg.StateInReviewLabel)
	if cfg.StateInReviewLabel == "" {
		cfg.StateInReviewLabel = stateInReviewLabelDefault
	}

	cfg.AgentModel = strings.TrimSpace(cfg.AgentModel)
	if cfg.AgentModel == "" {
		cfg.AgentModel = modelGPT54
	}
	cfg.AgentReasoningEffort = strings.TrimSpace(strings.ToLower(cfg.AgentReasoningEffort))
	// Codex CLI expects "xhigh" for the highest reasoning effort.
	switch cfg.AgentReasoningEffort {
	case "extra-high", "extra_high", "extra high", "x-high":
		cfg.AgentReasoningEffort = "xhigh"
	}
	if cfg.AgentReasoningEffort == "" {
		cfg.AgentReasoningEffort = "high"
	}
	cfg.AgentBaseBranch = strings.TrimSpace(cfg.AgentBaseBranch)
	if cfg.AgentBaseBranch == "" {
		cfg.AgentBaseBranch = "main"
	}
	cfg.RuntimeMode = strings.TrimSpace(strings.ToLower(cfg.RuntimeMode))
	if cfg.RuntimeMode != runtimeModeFullEnv {
		cfg.RuntimeMode = runtimeModeCodeOnly
	}
	cfg.RuntimeTargetEnv = strings.TrimSpace(strings.ToLower(cfg.RuntimeTargetEnv))
	cfg.RuntimeBuildRef = strings.TrimSpace(cfg.RuntimeBuildRef)
	cfg.RuntimeAccessProfile = strings.TrimSpace(strings.ToLower(cfg.RuntimeAccessProfile))

	cfg.ProjectID = strings.TrimSpace(cfg.ProjectID)
	cfg.ControlPlaneGRPCTarget = strings.TrimSpace(cfg.ControlPlaneGRPCTarget)
	cfg.MCPBaseURL = strings.TrimRight(strings.TrimSpace(cfg.MCPBaseURL), "/")
	cfg.MCPBearerToken = strings.TrimSpace(cfg.MCPBearerToken)
	cfg.RepositoryFullName = strings.TrimSpace(cfg.RepositoryFullName)
	cfg.AgentKey = strings.TrimSpace(cfg.AgentKey)
	cfg.RunTargetBranch = strings.TrimSpace(cfg.RunTargetBranch)
	if cfg.ExistingPRNumber < 0 {
		cfg.ExistingPRNumber = 0
	}
	cfg.AgentDisplayName = strings.TrimSpace(cfg.AgentDisplayName)
	cfg.GitBotUsername = strings.TrimSpace(cfg.GitBotUsername)
	cfg.GitBotMail = strings.TrimSpace(cfg.GitBotMail)
	cfg.OpenAIAPIKey = strings.TrimSpace(cfg.OpenAIAPIKey)
	if cfg.DiscussionPollInterval <= 0 {
		cfg.DiscussionPollInterval = 15 * time.Second
	}

	return cfg, nil
}
