//go:build !fasthttp

package gitea

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"net/url"
	"strings"
	"time"

	"code.gitea.io/sdk/gitea"
	"codeberg.org/codeberg/pages/server/cache"
)

type Client struct {
	sdkClient         *gitea.Client
	fileResponseCache cache.SetGetKey
}

func NewClient(giteaRoot, giteaAPIToken string, fileResponseCache cache.SetGetKey) (*Client, error) {
	rootURL, err := url.Parse(giteaRoot)
	giteaRoot = strings.Trim(rootURL.String(), "/")

	stdClient := http.Client{Timeout: 10 * time.Second}

	sdk, err := gitea.NewClient(giteaRoot, gitea.SetHTTPClient(&stdClient), gitea.SetToken(giteaAPIToken))
	return &Client{
		sdkClient:         sdk,
		fileResponseCache: fileResponseCache,
	}, err
}

func (client *Client) GiteaRawContent(targetOwner, targetRepo, ref, resource string) ([]byte, error) {
	rawBytes, resp, err := client.sdkClient.GetFile(targetOwner, targetRepo, ref, resource)
	if err != nil {
		return nil, err
	}

	switch resp.StatusCode {
	case http.StatusOK:
		return rawBytes, nil
	case http.StatusNotFound:
		return nil, ErrorNotFound
	default:
		return nil, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
	}
}

func (client *Client) ServeRawContent(targetOwner, targetRepo, ref, resource string) (io.ReadCloser, error) {
	// TODO: add func that return io.ReadCloser or io.ReadSeekCloser?
	rawBytes, resp, err := client.sdkClient.GetFile(targetOwner, targetRepo, ref, resource)
	if err != nil {
		return nil, err
	}

	switch resp.StatusCode {
	case http.StatusOK:
		return io.NopCloser(bytes.NewReader(rawBytes)), nil
	case http.StatusNotFound:
		return nil, ErrorNotFound
	default:
		return nil, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
	}
}

func (client *Client) GiteaGetRepoBranchTimestamp(repoOwner, repoName, branchName string) (time.Time, error) {
	branch, resp, err := client.sdkClient.GetRepoBranch(repoOwner, repoName, branchName)
	if err != nil {
		return time.Time{}, err
	}
	if resp.StatusCode != http.StatusOK {
		return time.Time{}, fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
	}
	return branch.Commit.Timestamp, nil
}

func (client *Client) GiteaGetRepoDefaultBranch(repoOwner, repoName string) (string, error) {
	repo, resp, err := client.sdkClient.GetRepo(repoOwner, repoName)
	if err != nil {
		return "", err
	}
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("unexpected status code '%d'", resp.StatusCode)
	}
	return repo.DefaultBranch, nil
}