package palauthiam

import (
	"context"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"
)

type PalAuthIAMClient struct {
	clientId string
	clientSecret string
	baseURL string
}

func InitClient(clientId, clientSecret string) *PalAuthIAMClient {
	return &PalAuthIAMClient{
		clientId: clientId,
		clientSecret: clientSecret,
		baseURL: "https://auth.palk.me/iam",
	}
}

func (c *PalAuthIAMClient) SetBaseURL(baseURL string) {
	c.baseURL = baseURL
}

func mapToQuery(variables map[string]string) (output string) {
	for key, value := range variables {
		output += fmt.Sprintf("%s=%s&", key, value)
	}

	if len(variables) != 0 {
		output = strings.TrimSuffix(output, "&")
	}
	return output
}

func (c *PalAuthIAMClient) buildURL(path string, query map[string]string) string {
	return fmt.Sprintf("%s%s?%s", c.baseURL, path, mapToQuery(query))
}

func (c *PalAuthIAMClient) runRequest(req *http.Request, mapTo interface{}) error {
	res, err := http.DefaultClient.Do(req)
	if err != nil {
		return fmt.Errorf("making request: %s", err)
	}

	resBody, err := io.ReadAll(res.Body)
	if err != nil {
		return fmt.Errorf("read response body: %s", err)
	}

	if res.StatusCode >= 200 && res.StatusCode < 300 {
		err = json.Unmarshal(resBody, mapTo)
		if err != nil {
			return fmt.Errorf("decode JSON response: %s", err)
		}
	} else if res.StatusCode >= 400 && res.StatusCode < 500 {
		return &IAMError{
			ServerMessage: string(resBody),
		}
	}

	return nil
}

func (c *PalAuthIAMClient) getRequest(
	ctx context.Context,
	path string,
	variables map[string]string,
	mapTo interface{},
) error {
	req, err := http.NewRequestWithContext(
		ctx,
		http.MethodGet,
		c.buildURL(path, variables),
		http.NoBody,
	)
	if err != nil {
		return fmt.Errorf("construct request: %s", err)
	}

	return c.runRequest(req, mapTo)
}