package web

import (
	"net/http"

	"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"
)

// TreeData contains data for rendering directory tree view.
type TreeData struct {
	RepoBaseData
	Ref          string
	Path         string
	Entries      git.Entries
	IsCommitHash bool
}

func repoTree(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
	}

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

	vars := mux.Vars(r)
	refAndPath := vars["refAndPath"]
	ref, path := parseRefAndPath(gr, refAndPath)

	if ref == "" {
		head, err := gr.HEAD()
		if err == nil && head != nil {
			ref = head.Name().Short()
		}
	}

	refObj, isCommitHash, 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
	}

	tree, err := gr.TreePath(refObj, path)
	if err != nil {
		logger.Debug("failed to get tree path", "repo", repo.Name(), "ref", ref, "path", path, "err", err)
		renderNotFound(w, r)
		return
	}

	entries, err := tree.Entries()
	if err != nil {
		logger.Debug("failed to get tree entries", "err", err)
		renderInternalServerError(w, r)
		return
	}

	entries.Sort()

	defaultBranch := getDefaultBranch(gr)

	data := TreeData{
		RepoBaseData: RepoBaseData{
			BaseData: BaseData{
				ServerName: cfg.Name,
				ActiveTab:  "tree",
			},
			Repo:          repo,
			DefaultBranch: defaultBranch,
		},
		Ref:          ref,
		Path:         path,
		Entries:      entries,
		IsCommitHash: isCommitHash,
	}

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