package gitea

import (
	"bytes"
	"context"
	"fmt"
	"io"

	"code.gitea.io/sdk/gitea"
	"git.schreifuchs.ch/schreifuchs/pierre-bot/internal/pierre"
)

type Adapter struct {
	client *gitea.Client
}

func New(baseURL, token string) (*Adapter, error) {
	client, err := gitea.NewClient(baseURL, gitea.SetToken(token))
	if err != nil {
		return nil, err
	}
	return &Adapter{
		client: client,
	}, nil
}

func (g *Adapter) GetDiff(ctx context.Context, owner, repo string, prID int) (io.ReadCloser, error) {
	g.client.SetContext(ctx)
	diff, _, err := g.client.GetPullRequestDiff(owner, repo, int64(prID), gitea.PullRequestDiffOptions{})
	if err != nil {
		return nil, err
	}
	return io.NopCloser(bytes.NewReader(diff)), nil
}

func (g *Adapter) AddComment(ctx context.Context, owner, repo string, prID int, comment pierre.Comment) error {
	g.client.SetContext(ctx)
	opts := gitea.CreatePullReviewOptions{
		State: gitea.ReviewStateComment,
		Comments: []gitea.CreatePullReviewComment{
			{
				Path:       comment.File,
				Body:       comment.Message,
				NewLineNum: int64(comment.Line),
			},
		},
	}
	_, _, err := g.client.CreatePullReview(owner, repo, int64(prID), opts)
	return err
}

// GetFileContent returns the file content at a given path and ref (commit SHA).
func (g *Adapter) GetFileContent(ctx context.Context, owner, repo, path, ref string) (string, error) {
	g.client.SetContext(ctx)
	// The SDK's GetFile returns the raw bytes of the file.
	data, _, err := g.client.GetFile(owner, repo, ref, path)
	if err != nil {
		return "", err
	}
	return string(data), nil
}

// GetPRHeadSHA fetches the pull request and returns the head commit SHA.
func (g *Adapter) GetPRHeadSHA(ctx context.Context, owner, repo string, prID int) (string, error) {
	g.client.SetContext(ctx)
	// GetPullRequest returns the detailed PR information.
	pr, _, err := g.client.GetPullRequest(owner, repo, int64(prID))
	if err != nil {
		return "", err
	}
	if pr == nil || pr.Head == nil {
		return "", fmt.Errorf("pull request %d has no head information", prID)
	}
	return pr.Head.Sha, nil
}
