package imp

import (
	"errors"
	"testing"

	l4g "github.com/alecthomas/log4go"
	"github.com/dailymotion/allure-go"
	"github.com/tidbcloud/qa-PlatformAPIAuto/common"
	"github.com/tidbcloud/qa-PlatformAPIAuto/models"
)

type baseImport struct {
	*common.DbassRequestInfo

	T              *testing.T
	ImportId       string
	Data           *models.ClusterIdImportsBody
	PreviewData    *models.ImportsPreviewBody
	PrecheckData   *models.ImportsValidateBody
	SearchFileData *models.ImportsSearchimportfilesBody
}

func (i *baseImport) Create() {
	if i.ClusterId == "" {
		errMsg := errors.New("cluster id is empty, can't import data")
		l4g.Error(errMsg)
		allure.FailNow(errMsg)
		return
	}
	// wait until cluster status becomes NORMAL before starting import
	_, _, _, _ = common.CheckClusterStatus(
		i.T,
		i.CommonEnv.ProjectId,
		i.ClusterId,
		"$.cluster.status",
		"NORMAL",
		60,
	)
	pathParam := map[string]string{
		"org_id":     i.CommonEnv.OrgId,
		"project_id": i.CommonEnv.ProjectId,
		"cluster_id": i.ClusterId,
	}

	callResp := i.DbassRequest(i.T, "import", i.Data, pathParam, nil, nil)
	httpInfo := common.ParseHttpInfo(callResp)
	if httpInfo.RespStatusCode != common.StatusOK {
		allure.FailNow(errors.New("create import failed"))
	}

	resp := &models.DataflowClusterImportID{}
	httpInfo.UnmarshalRespBody(resp)

	i.ImportId = *resp.ID
}

func (i *baseImport) PreCheck() {
	if i.ClusterId == "" {
		errMsg := errors.New("cluster id is empty, can't pre check data")
		l4g.Error(errMsg)
		allure.FailNow(errMsg)
		return
	}
	pathParam := map[string]string{
		"org_id":     i.CommonEnv.OrgId,
		"project_id": i.CommonEnv.ProjectId,
		"cluster_id": i.ClusterId,
	}

	callResp := i.DbassRequest(i.T, "importValidate", i.PrecheckData, pathParam, nil, nil)
	httpInfo := common.ParseHttpInfo(callResp)
	if httpInfo.RespStatusCode != common.StatusOK {
		allure.FailNow(errors.New("create import failed"))
	}
}

func (i *baseImport) GetAKSKInfo() (string, string) {
	return i.CommonEnv.AccessKey, i.CommonEnv.SecretKey
}

func (i *baseImport) PreView() {
	/*if i.ClusterId == "" {
		errMsg := errors.New("cluster id is empty, can't pre check data")
		l4g.Error(errMsg)
		allure.FailNow(errMsg)
		return
	}
	pathParam := map[string]string{
		"org_id":     i.CommonEnv.OrgId,
		"project_id": i.CommonEnv.ProjectId,
		"cluster_id": i.ClusterId,
	}

	callResp := i.DbassRequest(i.T, "importPreview", i.PreviewData, pathParam, nil, nil)
	httpInfo := common.ParseHttpInfo(callResp)
	if httpInfo.RespStatusCode != common.StatusOK {
		allure.FailNow(errors.New("preview import failed"))
	}

	resp := &models.{}
	httpInfo.UnmarshalRespBody(resp)

	if resp.BaseResp.ErrCode != "0" || len(resp.Schemas) == 0{
		allure.FailNow(errors.New("preview import failed, errcode is not 0 or schemas len is 0"))
	}*/
}

func (i *baseImport) Cancel() {
	if i.ClusterId == "" || i.ImportId == "" {
		errMsg := errors.New("cluster id or import id is empty, can't cancel import")
		l4g.Error(errMsg)
		allure.FailNow(errMsg)
		return
	}

	pathParam := map[string]string{
		"org_id":     i.CommonEnv.OrgId,
		"project_id": i.CommonEnv.ProjectId,
		"cluster_id": i.ClusterId,
		"id":         i.ImportId,
	}

	callResp := i.DbassRequest(i.T, "cancleImport", "", pathParam, nil, nil)
	httpInfo := common.ParseHttpInfo(callResp)
	if httpInfo.RespStatusCode != common.StatusOK {
		allure.FailNow(errors.New("cancel import failed"))
	}
}

func (i *baseImport) Get() (*models.DataflowImportGetResp, error) {
	if i.ClusterId == "" || i.ImportId == "" {
		errMsg := errors.New("cluster id or import id is empty, can't check import status")
		l4g.Warn(errMsg)
		return nil, errMsg
	}

	pathParam := map[string]string{
		"org_id":     i.CommonEnv.OrgId,
		"project_id": i.CommonEnv.ProjectId,
		"cluster_id": i.ClusterId,
		"id":         i.ImportId,
	}

	callResp := i.DbassRequest(i.T, "getImportInfo", "", pathParam, nil, nil)
	httpInfo := common.ParseHttpInfo(callResp)
	if httpInfo.RespStatusCode != common.StatusOK {
		l4g.Error("get import info failed")
		return nil, errors.New("get import info failed")
	}

	resp := &models.DataflowImportGetResp{}
	httpInfo.UnmarshalRespBody(resp)

	return resp, nil
}

func (i *baseImport) SetImportData(data *models.ClusterIdImportsBody) {
	i.Data = data
}

func (i *baseImport) SetPrecheckData(data *models.ImportsValidateBody) {
	i.PrecheckData = data
}

func (i *baseImport) SetPreviewData(data *models.ImportsPreviewBody) {
	i.PreviewData = data
}

func (i *baseImport) SetSearchFileData(data *models.ImportsSearchimportfilesBody) {
	i.SearchFileData = data
}

func (i *baseImport) GetTargetTable() {
	if i.ClusterId == "" {
		errMsg := errors.New("cluster id is empty, can't get target table")
		l4g.Warn(errMsg)
		allure.FailNow(errMsg)
		return
	}

	pathParam := map[string]string{
		"org_id":     i.CommonEnv.OrgId,
		"project_id": i.CommonEnv.ProjectId,
		"cluster_id": i.ClusterId,
	}

	callResp := i.DbassRequest(i.T, "getTargetTables", "", pathParam, nil, nil)
	httpInfo := common.ParseHttpInfo(callResp)
	if httpInfo.RespStatusCode != common.StatusOK {
		l4g.Error("get target table failed")
		allure.FailNow(errors.New("get target table failed"))
		return
	}

	resp := &models.DataflowImportsGetClusterTablesResp{}
	httpInfo.UnmarshalRespBody(resp)

	for _, schema := range resp.Schemas {
		if schema.SchemaName != "" && len(schema.Tables) != 0 {
			if schema.Tables[0].TableName != "" {
				return
			}
		}
	}

	allure.FailNow(errors.New("get target table failed, target schema or table is null"))
}

func (i *baseImport) SearchImportFiles() string {
	if i.ClusterId == "" {
		errMsg := errors.New("cluster id is empty, can't search import files")
		l4g.Error(errMsg)
		allure.FailNow(errMsg)
		return ""
	}
	pathParam := map[string]string{
		"org_id":     i.CommonEnv.OrgId,
		"project_id": i.CommonEnv.ProjectId,
		"cluster_id": i.ClusterId,
	}

	callResp := i.DbassRequest(i.T, "searchImportFiles", i.SearchFileData, pathParam, nil, nil)
	httpInfo := common.ParseHttpInfo(callResp)
	if httpInfo.RespStatusCode != common.StatusOK {
		allure.FailNow(errors.New("search import files failed"))
		return ""
	}

	resp := &models.DataflowImportsSearchImportFilesResp{}
	httpInfo.UnmarshalRespBody(resp)

	if resp.WarningMessage != "" || len(resp.TargetTables) == 0 {
		allure.FailNow(errors.New("search import files failed, warningMessage is not null"))
	}
	i.PrecheckData.TargetTableInfos[0].MatchedUri = resp.TargetTables[0].SourceUri
	return resp.TargetTables[0].SourceUri
}
