package addrproviders

import (
	"bytes"
	"context"
	"fmt"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"go-dyndns/util"
	"io"
	"net/http"
	"testing"
)

func Test_webProvider_GetIP_Success(t *testing.T) {
	config := &WebProviderConfig{
		Url: "http://checkip.dyndns.com/",
	}

	httpClient := setupWebHttpClientMockWithIp("http://checkip.dyndns.com/", "127.0.0.1")

	provider := newWebProvider(config, httpClient)
	ip, err := provider.GetIPv4(context.Background())

	assert.Nil(t, err)
	assert.Equal(t, "127.0.0.1", ip.String())

	httpClient.AssertExpectations(t)
}

func Test_webProvider_GetIP_MalformedIP(t *testing.T) {
	config := &WebProviderConfig{
		Url: "http://checkip.dyndns.com/",
	}

	httpClient := setupWebHttpClientMockWithIp("http://checkip.dyndns.com/", "asdf")

	provider := newWebProvider(config, httpClient)
	_, err := provider.GetIPv4(context.Background())

	assert.ErrorIs(t, err, ParseIpError)
	httpClient.AssertExpectations(t)
}

func Test_webProvider_GetIP_InvalidResponseHtml(t *testing.T) {
	config := &WebProviderConfig{
		Url: "http://checkip.dyndns.com/",
	}

	httpClient := setupWebHttpClientMock("http://checkip.dyndns.com/", "asdf")

	provider := newWebProvider(config, httpClient)
	_, err := provider.GetIPv4(context.Background())

	assert.ErrorIs(t, err, InvalidResponseError)
	httpClient.AssertExpectations(t)
}

func setupWebHttpClientMockWithIp(url, ip string) *util.MockHttpClient {
	return setupWebHttpClientMock(
		url,
		fmt.Sprintf("<html><head><title>Current IP Check</title></head><body>Current IP Address: %s</body></html>", ip),
	)
}

func setupWebHttpClientMock(url, responseText string) *util.MockHttpClient {
	httpClient := new(util.MockHttpClient)
	httpClient.On("Do", mock.MatchedBy(func(req *http.Request) bool { return req.URL.String() == url })).
		Return(&http.Response{
			Status:        "200 OK",
			StatusCode:    200,
			Proto:         "HTTP/1.1",
			ProtoMajor:    1,
			ProtoMinor:    1,
			Body:          io.NopCloser(bytes.NewBufferString(responseText)),
			ContentLength: int64(len(responseText)),
			Header:        make(http.Header, 0),
		}, nil)

	return httpClient
}
