package web

import (
	"net/http"

	"charm.land/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)

	repoDisplayName := repo.ProjectName()
	if repoDisplayName == "" {
		repoDisplayName = repo.Name()
	}

	title := repo.Name()
	if path != "." {
		title += "/" + path
	}
	title += " at "
	if isCommitHash && len(ref) > 7 {
		title += ref[:7]
	} else {
		title += ref
	}
	title += " | " + repoDisplayName

	// Build fallback description matching title information
	descFallback := "Browse "
	if path != "." {
		descFallback += path + " at "
	}
	if isCommitHash && len(ref) > 7 {
		descFallback += ref[:7]
	} else {
		descFallback += ref
	}
	descFallback += " in " + repoDisplayName

	description := getRepoDescriptionOrFallback(repo, descFallback)

	data := TreeData{
		RepoBaseData: RepoBaseData{
			BaseData: BaseData{
				ServerName:  cfg.Name,
				ActiveTab:   "tree",
				Title:       title,
				Description: description,
			},
			Repo:          repo,
			DefaultBranch: defaultBranch,
			HasGitBug:     hasGitBug(ctx, repo),
		},
		Ref:          ref,
		Path:         path,
		Entries:      entries,
		IsCommitHash: isCommitHash,
	}

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