package ipipcli

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	"braces.dev/errtrace"
	"github.com/ipipdotnet/ipdb-go"

	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/domain/adapter/ipip"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/pkg/config"
)

func NewIPIP() ipip.Client {
	if config.Global().IPIPServer.LocalMode {
		return newFakeIPIPImpl()
	}

	return newIPIPImpl()
}

type ipipImpl struct {
	httpClient *http.Client
	address    string
}

func newIPIPImpl() ipip.Client {
	return &ipipImpl{
		httpClient: &http.Client{},
		address:    config.Global().IPIPServer.Address,
	}
}

func (i *ipipImpl) IP2CityInfo(ip string) (*ipdb.CityInfo, error) {
	url := fmt.Sprintf("http://%s/ip/%s", i.address, ip)
	req, err := http.NewRequest(http.MethodGet, url, http.NoBody)
	if err != nil {
		return nil, errtrace.Wrap(err)
	}
	resp, err := i.httpClient.Do(req)
	if err != nil {
		return nil, errtrace.Wrap(err)
	}
	defer resp.Body.Close()

	body, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, errtrace.Wrap(err)
	}

	var res ipdb.CityInfo
	err = json.Unmarshal(body, &res)
	if err != nil {
		return nil, errtrace.Wrap(err)
	}
	return &res, nil
}
