package billing

import (
	"bytes"
	"errors"
	"io"
	"io/ioutil"
	"net/http"

	"github.com/tidbcloud/central-sdk/db/tenant"
)

type FakeHttpClient struct {
	StatusCode int
	Header     http.Header
	Body       []byte

	Error       error
	ReaderError error
}

func (f *FakeHttpClient) Do(r *http.Request) (*http.Response, error) {
	var rc io.ReadCloser = &ByteReaderCloser{
		Reader: bytes.NewReader(f.Body),
	}
	if f.ReaderError != nil {
		rc = &ErrorReaderCloser{f.ReaderError}
	}
	return &http.Response{
		StatusCode: f.StatusCode,
		Header:     f.Header,
		Body:       rc,
	}, f.Error
}

type ByteReaderCloser struct {
	*bytes.Reader
}

func (r *ByteReaderCloser) Close() error {
	return nil
}

type ErrorReaderCloser struct {
	err error
}

func (r *ErrorReaderCloser) Close() error {
	return r.err
}

func (r *ErrorReaderCloser) Read(p []byte) (n int, err error) {
	return 0, r.err
}

type AllowAll struct{}

func (p *AllowAll) Auth(r *http.Request) error {
	return nil
}

type DeniedAll struct{}

func (p *DeniedAll) Auth(r *http.Request) error {
	return errors.New("permission denied")
}

type RecordParameterTransport struct {
	ApiPath string
	Method  string
	Payload []byte
}

func (t *RecordParameterTransport) Submit(apiPath, method string, payload io.Reader) ([]byte, error) {
	t.Method = method
	t.ApiPath = apiPath
	if payload != nil {
		b, _ := ioutil.ReadAll(payload)
		t.Payload = b
	}
	return []byte("{}"), nil
}

type FakeTransport struct {
	Error error
	Data  []byte
}

func (t *FakeTransport) Submit(apiPath, method string, payload io.Reader) ([]byte, error) {
	return t.Data, t.Error
}

type NoPermissionCheck struct{}

func (n *NoPermissionCheck) HasPermission(*tenant.User) bool {
	return false
}
