//! Route handlers for branch pages.
//!
//! Covers two routes: the branch list (`/{repo}/branches`) and the branch
//! detail page (`/{repo}/branches/{*branch}`).  The detail handler resolves
//! the branch ref to its tip commit and walks ancestors to produce a log view.

use askama::Template;
use askama_web::WebTemplate;
use axum::extract::{Path, Query, State};
use axum::response::IntoResponse;
use serde::Deserialize;

use crate::config::SiteConfig;
use crate::error::Result;
use crate::git;
use crate::routes::{AppState, RepoName};

const PAGE_SIZE: usize = 100;

#[derive(Deserialize)]
pub(super) struct BranchPath {
    branch: String,
}

#[derive(Deserialize)]
pub(super) struct Pagination {
    #[serde(default)]
    after: Option<String>,
}

/// Template context for the branch list page.
#[derive(Template, WebTemplate)]
#[template(path = "branch_list.html")]
struct BranchList {
    repo: String,
    branches: Vec<git::BranchInfo>,
    site: std::sync::Arc<SiteConfig>,
}

/// Template context for the branch detail (log) page.
#[derive(Template, WebTemplate)]
#[template(path = "branch_detail.html")]
struct BranchDetail {
    repo: String,
    branch: String,
    tip_sha: String,
    commits: Vec<git::CommitSummary>,
    after: Option<String>,
    next_cursor: Option<String>,
    site: std::sync::Arc<SiteConfig>,
}

/// Renders the full list of branches for a repository.
pub async fn list(
    State(state): State<AppState>,
    RepoName(repo): RepoName,
) -> Result<impl IntoResponse> {
    let git_repo = git::open_repo(&state.root, &repo)?;
    let branches = git::load_branches(&git_repo);
    Ok(BranchList {
        repo,
        branches,
        site: state.site,
    })
}

/// Renders a paginated log of commits reachable from the tip of the given branch.
pub async fn detail(
    State(state): State<AppState>,
    RepoName(repo): RepoName,
    Path(params): Path<BranchPath>,
    Query(pagination): Query<Pagination>,
) -> Result<impl IntoResponse> {
    let after = pagination.after.filter(|s| !s.is_empty());
    let git_repo = git::open_repo(&state.root, &repo)?;
    let log = git::load_branch_log(&git_repo, &params.branch, after.clone(), PAGE_SIZE)?;

    Ok(BranchDetail {
        repo,
        branch: params.branch,
        tip_sha: log.tip_sha,
        commits: log.commits,
        after,
        next_cursor: log.next_cursor,
        site: state.site,
    })
}
