package netbox

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

	"git.faercol.me/faercol/topology-map/internal/models"
)

const (
	devicesRoute   = "dcim/devices"
	cablesRoute    = "dcim/cables"
	vmsRoute       = "virtualization/virtual-machines"
	interfaceRoute = "dcim/interfaces"
)

type vmsResponse struct {
	Results []models.VM `json:"results"`
}

type deviceResponse struct {
	Results []models.Device `json:"results"`
}

type cableResponse struct {
	Results []models.Cable `json:"results"`
}

type interfaceResponse struct {
	Results []models.Interface `json:"results"`
}

type NetboxClient struct {
	httpClt       *http.Client
	netboxBaseURL string
	netboxToken   string
}

func (c *NetboxClient) queryAPI(route string) ([]byte, error) {
	query, err := http.NewRequest("GET", c.netboxBaseURL+route, nil)
	if err != nil {
		return nil, err
	}
	query.Header.Set("Authorization", "Token "+c.netboxToken)

	resp, err := c.httpClt.Do(query)
	if err != nil {
		return nil, err
	}

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

func (c *NetboxClient) GetDevices() ([]models.Device, error) {
	var res deviceResponse

	respBody, err := c.queryAPI(devicesRoute)
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(respBody, &res); err != nil {
		return nil, err
	}

	return res.Results, nil
}

func (c *NetboxClient) GetInterfaces() ([]models.Interface, error) {
	var res interfaceResponse

	respBody, err := c.queryAPI(interfaceRoute)
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(respBody, &res); err != nil {
		return nil, err
	}
	return res.Results, nil
}

func (c *NetboxClient) GetCables() ([]models.Cable, error) {
	var res cableResponse

	respBody, err := c.queryAPI(cablesRoute)
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(respBody, &res); err != nil {
		return nil, err
	}

	return res.Results, nil
}

func (c *NetboxClient) GetVMs() ([]models.VM, error) {
	var res vmsResponse

	respBody, err := c.queryAPI(vmsRoute)
	if err != nil {
		return nil, err
	}

	if err := json.Unmarshal(respBody, &res); err != nil {
		return nil, err
	}

	return res.Results, nil
}

func NewClient(baseURL, token string) *NetboxClient {
	return &NetboxClient{
		httpClt:       http.DefaultClient,
		netboxBaseURL: baseURL,
		netboxToken:   token,
	}
}
