package client

import (
	"fmt"
	"git.sxidc.com/go-tools/api_binding/http_binding/response"
	"git.sxidc.com/service-supports/ds-sdk/client/request"
	"net/url"
)

const (
	executeRawSqlUrl = "/ds/api/v1/sql/rawSql/execute"
	parseSqlSpecUrl  = "/ds/api/v1/sql/spec/parse"
	createSqlUrl     = "/ds/api/v1/sql/create"
	deleteSqlUrl     = "/ds/api/v1/sql/delete"
	getSqlsUrl       = "/ds/api/v1/sql/query"
	executeSqlUrl    = "/ds/api/v1/sql/execute"
)

func (c *Client) ExecuteRawSql(token string, baseUrl string,
	namespace string, dataSource string, sql string) ([]map[string]any, error) {
	fullUrl, err := url.JoinPath(baseUrl, executeRawSqlUrl)
	if err != nil {
		return nil, err
	}

	resp := new(struct {
		response.MsgResponse
		Results []map[string]any `json:"results"`
	})

	err = c.post(token, fullUrl, &request.ExecuteRawSqlRequest{
		Namespace:  namespace,
		DataSource: dataSource,
		Sql:        sql,
	}, resp)
	if err != nil {
		return nil, err
	}

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

	return resp.Results, nil
}

func (c *Client) ParseSqlSpec(token string, baseUrl string, specJson string, executeParams map[string]any) (string, error) {
	fullUrl, err := url.JoinPath(baseUrl, parseSqlSpecUrl)
	if err != nil {
		return "", err
	}

	resp := new(struct {
		response.MsgResponse
		Parsed string `json:"parsed"`
	})

	err = c.post(token, fullUrl, &request.ParseSqlSpecRequest{
		Spec:          specJson,
		ExecuteParams: executeParams,
	}, resp)
	if err != nil {
		return "", err
	}

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

	return resp.Parsed, nil
}

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

	resp := new(response.MsgResponse)

	err = c.post(token, fullUrl, &request.CreateSqlRequest{
		Namespace:  namespace,
		DataSource: dataSource,
		Name:       name,
		Spec:       spec,
	}, resp)
	if err != nil {
		return err
	}

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

	return nil
}

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

	resp := new(response.MsgResponse)

	err = c.post(token, fullUrl, &request.DeleteSqlRequest{
		Namespace:  namespace,
		DataSource: dataSource,
		Name:       name,
	}, resp)
	if err != nil {
		return err
	}

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

	return nil
}

func (c *Client) GetSqls(token string, baseUrl string, namespace string, dataSource string, name string) ([]SqlInfo, error) {
	fullUrl, err := url.JoinPath(baseUrl, getSqlsUrl)
	if err != nil {
		return nil, err
	}

	resp := new(response.InfosResponse[SqlInfo])

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

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

	return resp.Infos, nil
}

func (c *Client) ExecuteSql(token string, baseUrl string,
	namespace string, dataSource string, name string, executeParams map[string]any) ([]map[string]any, error) {
	fullUrl, err := url.JoinPath(baseUrl, executeSqlUrl)
	if err != nil {
		return nil, err
	}

	resp := new(struct {
		response.MsgResponse
		Results []map[string]any `json:"results"`
	})

	err = c.post(token, fullUrl, &request.ExecuteSqlRequest{
		Namespace:     namespace,
		DataSource:    dataSource,
		Name:          name,
		ExecuteParams: executeParams,
	}, resp)
	if err != nil {
		return nil, err
	}

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

	return resp.Results, nil
}