//! App-wide constants.
//!
//! # Bounded Context: Identity & Configuration Names
//!
//! Single source of truth for the app name, config filenames, env var
//! names, version strings, and URLs. Every other module imports from
//! here — a rename only requires changing this file.

// ── Version & build metadata ────────────────────────────────────────

/// Semantic version from Cargo.toml (patched from the git tag in CI).
pub const VERSION: &str = env!("CARGO_PKG_VERSION");

/// Full version string including dev metadata.
///
/// For release builds (HEAD tagged `v{VERSION}`) this equals [`VERSION`].
/// For development builds it appends `-dev+{GIT_SHA}` so that diagnostics
/// can distinguish local builds from released ones.
pub const FULL_VERSION: &str = env!("FULL_VERSION");

/// Short git commit hash at build time, or `"unknown"`.
pub const GIT_SHA: &str = env!("GIT_SHA");

/// Build date (UTC, `YYYY-MM-DD`), or `"unknown"`.
pub const BUILD_DATE: &str = env!("BUILD_DATE");

/// Compilation target triple (e.g. `x86_64-unknown-linux-gnu`).
pub const TARGET: &str = env!("TARGET");

/// User-Agent header for HTTP requests.
pub const USER_AGENT: &str = concat!("chronikl/", env!("CARGO_PKG_VERSION"));

// ── App identity ────────────────────────────────────────────────────

/// Display name of the tool (lowercase).
pub const APP_NAME: &str = "chronikl";

/// Local config filename (e.g. `.chronikl.toml` in repo root).
pub const CONFIG_FILENAME: &str = ".chronikl.toml";

/// Directory name under `~/.config/` for global config and cache.
pub const CONFIG_DIR: &str = "chronikl";

/// AI-generated content disclosure notice.
pub const AI_DISCLOSURE: &str =
    "Generated by chronikl — AI-powered release notes. Review before publishing.";

// ── GitHub releases (self-update) ───────────────────────────────────

/// GitHub owner/repo for release downloads.
pub const GITHUB_REPO: &str = "nsrosenqvist/chronikl";

/// GitHub API endpoint for the latest release metadata.
pub const GITHUB_RELEASES_LATEST_API: &str =
    "https://api.github.com/repos/nsrosenqvist/chronikl/releases/latest";

/// Build a download URL for a release asset.
pub fn release_asset_url(tag: &str, target: &str) -> String {
    format!(
        "https://github.com/{}/releases/download/{}/chronikl-{}.tar.gz",
        GITHUB_REPO, tag, target
    )
}

/// Build a download URL for the SHA256SUMS file of a release.
pub fn release_checksums_url(tag: &str) -> String {
    format!(
        "https://github.com/{}/releases/download/{}/SHA256SUMS",
        GITHUB_REPO, tag
    )
}

// ── Environment variable names ──────────────────────────────────────

pub const ENV_PROVIDER: &str = "CHRONIKL_PROVIDER";
pub const ENV_MODEL: &str = "CHRONIKL_MODEL";
pub const ENV_API_KEY: &str = "CHRONIKL_API_KEY";
pub const ENV_BASE_URL: &str = "CHRONIKL_BASE_URL";

/// GitHub API token env vars, in lookup order.
///
/// `GITHUB_TOKEN` is the standard injected by GitHub Actions; `GH_TOKEN`
/// is `gh` CLI's convention. PR enrichment uses whichever is set first.
pub const GITHUB_TOKEN_ENV_VARS: &[&str] = &["GITHUB_TOKEN", "GH_TOKEN"];

/// GitHub Models inference endpoint (OpenAI-compatible chat completions).
/// Override per-call with `CHRONIKL_BASE_URL` — e.g. set to
/// `https://models.github.ai/orgs/<org>/inference` to bill an organisation.
pub const GITHUB_MODELS_BASE_URL: &str = "https://models.github.ai/inference";

// ── Retry constants ─────────────────────────────────────────────────

/// Maximum number of retry attempts for transient API errors.
pub const MAX_RETRIES: u32 = 5;

/// Initial backoff delay between retries.
pub const INITIAL_BACKOFF: std::time::Duration = std::time::Duration::from_secs(10);

/// Maximum backoff delay between retries.
pub const MAX_BACKOFF: std::time::Duration = std::time::Duration::from_secs(60);

// ── HTTP constants ──────────────────────────────────────────────────

/// Default total request timeout for outgoing HTTP calls.
pub const HTTP_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(10);

/// Default TCP connect timeout for outgoing HTTP calls.
pub const HTTP_CONNECT_TIMEOUT: std::time::Duration = std::time::Duration::from_secs(5);

// ── Ladder defaults ─────────────────────────────────────────────────

/// Per-call output cap for Tier 1 batched classification. Generous —
/// a 50-commit batch produces tiny per-entry verdicts.
pub const TIER1_MAX_OUTPUT_TOKENS: u64 = 8000;

/// Per-call output cap for Tier 2 per-commit classification. One
/// verdict object per call; small.
pub const TIER2_MAX_OUTPUT_TOKENS: u64 = 2000;

/// Per-call output cap for Tier 3 agent-loop turns. Higher than Tier 2
/// because agent turns can include text + tool calls.
pub const TIER3_MAX_OUTPUT_TOKENS: u64 = 4000;

/// Per-call output cap for the prose pass. Large because it produces
/// the entire release-notes document.
pub const PROSE_MAX_OUTPUT_TOKENS: u64 = 8000;

/// Maximum number of in-flight LLM calls per tier. Bounds concurrency
/// so we don't trigger provider rate limits while still amortizing
/// network latency across batches / per-commit calls.
pub const LLM_CONCURRENCY: usize = 8;

/// Maximum number of in-flight PR-platform API requests during
/// enrichment. Higher than LLM concurrency because forge REST APIs
/// (GitHub today, GitLab/Bitbucket later) are much faster per-call
/// and tolerate more parallelism.
pub const PR_CONCURRENCY: usize = 16;

/// Tier 1 batch size: how many commits go into a single classification call.
pub const DEFAULT_BATCH_SIZE: usize = 50;

/// Tier 2 confidence threshold: commits below this score get re-classified
/// with their diff included.
pub const DEFAULT_CONFIDENCE_THRESHOLD: f32 = 0.6;

/// Tier 2 maximum diff tokens per commit before truncation.
pub const DEFAULT_MAX_DIFF_TOKENS: usize = 4000;
