package web

import (
	"math"
	"net/http"
	"strconv"

	"github.com/charmbracelet/log/v2"
	"github.com/charmbracelet/soft-serve/git"
	"github.com/charmbracelet/soft-serve/pkg/config"
	"github.com/charmbracelet/soft-serve/pkg/proto"
	"github.com/gorilla/mux"
)

// CommitsData contains data for rendering commit history.
type CommitsData struct {
	RepoBaseData
	PaginationData
	Ref     string
	Commits git.Commits
}

// repoCommits handles commit history view.
func repoCommits(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()
	logger := log.FromContext(ctx)
	cfg := config.FromContext(ctx)
	repo := proto.RepositoryFromContext(ctx)
	if repo == nil {
		renderNotFound(w, r)
		return
	}
	vars := mux.Vars(r)
	ref := vars["ref"]

	gr, err := openRepository(repo)
	if err != nil {
		logger.Debug("failed to open repository", "repo", repo.Name(), "err", err)
		renderInternalServerError(w, r)
		return
	}

	refObj, _, err := resolveAndBuildRef(gr, ref)
	if err != nil {
		logger.Debug("failed to resolve ref or commit", "repo", repo.Name(), "ref", ref, "err", err)
		renderNotFound(w, r)
		return
	}

	page := 1
	if pageStr := r.URL.Query().Get("page"); pageStr != "" {
		if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
			page = p
		}
	}

	totalCommits, err := gr.CountCommits(refObj)
	if err != nil {
		logger.Debug("failed to count commits", "repo", repo.Name(), "ref", ref, "err", err)
		renderNotFound(w, r)
		return
	}

	totalPages := int(math.Ceil(float64(totalCommits) / float64(defaultCommitsPerPage)))
	if totalPages < 1 {
		totalPages = 1
	}

	if page > totalPages {
		page = totalPages
	}
	if page < 1 {
		page = 1
	}

	commits, err := gr.CommitsByPage(refObj, page, defaultCommitsPerPage)
	if err != nil {
		logger.Debug("failed to get commits", "repo", repo.Name(), "ref", ref, "err", err)
		renderNotFound(w, r)
		return
	}

	defaultBranch := getDefaultBranch(gr)

	data := CommitsData{
		RepoBaseData: RepoBaseData{
			BaseData: BaseData{
				ServerName: cfg.Name,
				ActiveTab:  "commits",
			},
			Repo:          repo,
			DefaultBranch: defaultBranch,
		},
		PaginationData: PaginationData{
			Page:        page,
			TotalPages:  totalPages,
			HasPrevPage: page > 1,
			HasNextPage: page < totalPages,
		},
		Ref:     ref,
		Commits: commits,
	}

	renderHTML(w, "commits.html", data)
}
