package client

import (
	"encoding/json"
	"fmt"
	"net/url"
	"strconv"
)

const (
	createDataSourceUrl = "/ds/api/v1/dataSource/create"
	deleteDataSourceUrl = "/ds/api/v1/dataSource/delete"
	getDataSourcesUrl   = "/ds/api/v1/dataSource/query"
	getDataSourceSpec   = "/ds/api/v1/dataSource/spec/get"
)

func (c *Client) CreateDataSource(token string, baseUrl string, namespace string, name string, typeStr string, spec map[string]any) error {
	fullUrl, err := url.JoinPath(baseUrl, createDataSourceUrl)
	if err != nil {
		return err
	}

	resp := new(MsgResponse)

	specJsonBytes, err := json.Marshal(spec)
	if err != nil {
		return err
	}

	err = c.post(token, fullUrl, map[string]any{
		"namespace": namespace,
		"name":      name,
		"type":      typeStr,
		"spec":      string(specJsonBytes),
	}, resp)
	if err != nil {
		return err
	}

	if !resp.Success {
		return fmt.Errorf(resp.Msg)
	}

	return nil
}

func (c *Client) DeleteDataSource(token string, baseUrl string, namespace string, name string) error {
	fullUrl, err := url.JoinPath(baseUrl, deleteDataSourceUrl)
	if err != nil {
		return err
	}

	resp := new(MsgResponse)

	err = c.post(token, fullUrl, map[string]any{
		"namespace": namespace,
		"name":      name,
	}, resp)
	if err != nil {
		return err
	}

	if !resp.Success {
		return fmt.Errorf(resp.Msg)
	}

	return nil
}

func (c *Client) GetDataSources(token string, baseUrl string, namespace string, name string, typeStr string, pageNo int, pageSize int) ([]DataSourceInfo, error) {
	fullUrl, err := url.JoinPath(baseUrl, getDataSourcesUrl)
	if err != nil {
		return nil, err
	}

	resp := new(InfosResponse[DataSourceInfo])

	err = c.get(token, fullUrl, map[string]string{
		"namespace": namespace,
		"name":      name,
		"type":      typeStr,
		"pageNo":    strconv.Itoa(pageNo),
		"pageSize":  strconv.Itoa(pageSize),
	}, resp)
	if err != nil {
		return nil, err
	}

	if !resp.Success {
		return nil, fmt.Errorf(resp.Msg)
	}

	return resp.Infos, nil
}

func (c *Client) GetDataSourceSpec(token string, baseUrl string, namespace string, name string) (string, error) {
	fullUrl, err := url.JoinPath(baseUrl, getDataSourceSpec)
	if err != nil {
		return "", err
	}

	resp := new(struct {
		MsgResponse
		Spec string `json:"spec"`
	})

	err = c.get(token, fullUrl, map[string]string{
		"namespace": namespace,
		"name":      name,
	}, resp)
	if err != nil {
		return "", err
	}

	if !resp.Success {
		return "", fmt.Errorf(resp.Msg)
	}

	return resp.Spec, nil
}