package import_cases

import (
	l4g "github.com/alecthomas/log4go"
	"github.com/tidbcloud/qa-PlatformAPIAuto/models"
	"testing"

	"github.com/dailymotion/allure-go"
	imp "github.com/tidbcloud/qa-PlatformAPIAuto/webScene/import"
)

/* csv_param.go contains csv param for import test cases.

csv param:
1. backslashescape
   a. \
2. delimitor:
   a. "
   b. '
3. header
   a. true
   b. false
4. separator
   a. ,
   b. ;
   c. :
   d: ' '
   f: \t
   g: |
5. terminator
   a. no terminator
   b. \n
   c. \r\n

cluster type:
1. dedicated cluster in aws
2. dedicated cluster in gcp
3. serverless cluster in aws
*/

type CsvParamTest struct {
	imp.BaseImportScene
}

func (t *CsvParamTest) Run() {
	allure.Test(
		t.T,
		allure.Epic("TestImportCsvParam"),
		allure.Feature("CreateImportTillCompleted"),
		allure.Description("1. backslashescape; 2. delimitor; 3. header; 4. separator; 5. terminator"),
		allure.Action(func() {
			t.CreateClusterStep()
			t.CreateTargetTableStep(csvPaTable)

			// If the provider is aws, we should create import credential one time in the test
			if t.Provider == imp.AwsProvider {
				t.CreateImportCredentialStep()
			}
			// Each test should delete import credential
			//defer t.DeleteImportCredentialStep()

			//backslashescape
			//import schema and data from s3
			t.initData(true, true, "backslashescape",
				"\"", ",", "NoTargetTable")
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(true, true, "backslashescape",
				"\"", ",", "TargetTable")
			t.CreateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			t.initData(false, true, "backslashescape",
				"\"", ",", "NoTargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(false, true, "backslashescape",
				"\"", ",", "TargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//delimitor '
			//import schema and data from s3
			t.initData(true, true, "delimitor_'",
				"'", ",", "NoTargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(true, true, "delimitor_'",
				"'", ",", "TargetTable")
			t.CreateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//header false
			//import schema and data from s3
			t.initData(true, false, "header_false",
				"\"", ",", "NoTargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(true, false, "header_false",
				"\"", ",", "TargetTable")
			t.CreateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//separator ;
			//import schema and data from s3
			t.initData(true, true, "separator_;",
				"\"", ";", "NoTargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(true, true, "separator_;",
				"\"", ";", "TargetTable")
			t.CreateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//separator :
			//import schema and data from s3
			t.initData(true, true, "separator_:",
				"\"", ":", "NoTargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(true, true, "separator_:",
				"\"", ":", "TargetTable")
			t.CreateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//separator \t
			//import schema and data from s3
			t.initData(true, true, "separator_\\t",
				"\"", "\\t", "NoTargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(true, true, "separator_\\t",
				"\"", "\\t", "TargetTable")
			t.CreateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//separator |
			//import schema and data from s3
			t.initData(true, true, "separator_|",
				"\"", "|", "NoTargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(true, true, "separator_|",
				"\"", "|", "TargetTable")
			t.CreateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//separator space
			//import schema and data from s3
			t.initData(true, true, "separator_space",
				"\"", " ", "NoTargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(true, true, "separator_space",
				"\"", " ", "TargetTable")
			t.CreateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//terminator no terminator
			//import schema and data from s3
			t.initData(true, false, "terminator_no",
				"\"", ",", "NoTargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(true, false, "terminator_no",
				"\"", ",", "TargetTable")
			t.CreateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//terminator \n
			//import schema and data from s3
			t.initData(true, true, "terminator_\\n",
				"\"", ",", "NoTargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(true, true, "terminator_\\n",
				"\"", ",", "TargetTable")
			t.CreateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//terminator \r\n
			//import schema and data from s3
			t.initData(true, true, "terminator_\\r\\n",
				"\"", ",", "NoTargetTable")
			t.TruncateTargetTableStep(csvPaTable)
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()

			//import into pre-created tables
			t.initData(true, true, "terminator_\\r\\n",
				"\"", ",", "TargetTable")
			t.CreateTargetTableStep(csvPaTable)
			t.SearchImportFiles()
			t.ImportPreCheckStep()
			t.CreateImportTillCompletedStep()
		}),
	)
}

// RunImportTestCsvParam is a test case for differ csv param import case.
func RunImportTestCsvParam(t *testing.T, clusterId, provider string, isServerless bool) {
	test := &CsvParamTest{}

	test.Init(t, clusterId, provider, isServerless)
	test.Run()
}

// the table used in this test case
var csvPaTable = imp.Table{
	SchemaName:      "test",
	TableName:       "person",
	SchemaStatement: "CREATE TABLE IF NOT EXISTS `test`.`person` ( `id` int DEFAULT NULL, `person` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL, `birthday` date DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;",
}

// initData is used to init import data for different providers
// data should be created previously now, maybe generated by code is better later
func (t *CsvParamTest) initData(backslashEscape, header bool, csvParam, delimiter, separator, model string) {
	var importData *models.ClusterIdImportsBody
	var searchImportFile *models.ImportsSearchimportfilesBody
	var precheckData *models.ImportsValidateBody
	var url string
	var csv *models.DataflowCustomCsvFormat
	if csvParam == "backslashescape" {
		url = "s3://import-scene-test/csv/backslashescape/delimiter=\";header=true;separator=,;backslashescape\\/"
	} else if csvParam == "delimitor_'" {
		url = "s3://import-scene-test/csv/delimitor/delimiter=';header=true;separator=,/"
	} else if csvParam == "header_false" {
		url = "s3://import-scene-test/csv/header/delimiter=\";header=false;separator=,/"
	} else if csvParam == "separator_;" {
		url = "s3://import-scene-test/csv/separator/delimiter=\";header=true;separator=;/"
	} else if csvParam == "separator_:" {
		url = "s3://import-scene-test/csv/separator/delimiter=\";header=true;separator=:/"
	} else if csvParam == "separator_\\t" {
		url = "s3://import-scene-test/csv/separator/delimiter=\";header=true;separator=\\t/"
	} else if csvParam == "separator_|" {
		url = "s3://import-scene-test/csv/separator/delimiter=\";header=true;separator=|/"
	} else if csvParam == "separator_space" {
		url = "s3://import-scene-test/csv/separator/delimiter=\";header=true;separator=space/"
	} else if csvParam == "terminator_no" {
		url = "s3://import-scene-test/csv/terminator/delimiter=\";header=false;separator=,;terminator=/"
	} else if csvParam == "terminator_\\n" {
		url = "s3://import-scene-test/csv/terminator/delimiter=\";header=false;separator=,;terminator=\\n/"
	} else if csvParam == "terminator_\\r\\n" {
		url = "s3://import-scene-test/csv/terminator/delimiter=\";header=false;separator=,;terminator=\\r\\n/"
	}
	csv = &models.DataflowCustomCsvFormat{BackslashEscape: backslashEscape, Delimiter: delimiter, Header: header, Null: "\\N", Separator: separator}
	if t.Provider == imp.AwsProvider {
		arn := t.ImportArnName()
		region := "ap-southeast-1"
		importData = &models.ClusterIdImportsBody{
			SourceUrl:      url,
			DataSourceType: int64(imp.ImportDataSourceTypeS3),
			Region:         region,
			DataFormat:     int64(imp.ImportDataFormatCsv),
			AwsRoleArn:     arn,
			CsvFormat:      csv,
		}
		precheckData = &models.ImportsValidateBody{
			AwsRoleArn:     arn,
			DataFormat:     int64(imp.ImportDataFormatCsv),
			DataSourceType: int64(imp.ImportDataSourceTypeS3),
			SourceUrl:      url,
			CheckItems:     []models.DataflowImportValidationItem{models.IMPORT_PRECHECK_DataflowImportValidationItem},
			CsvFormat:      csv,
		}
		searchImportFile = &models.ImportsSearchimportfilesBody{
			AwsRoleArn:     arn,
			DataFormat:     int64(imp.ImportDataFormatCsv),
			DataSourceType: int64(imp.ImportDataSourceTypeS3),
			SourceUri:      url,
		}
	} else {
		importData = &models.ClusterIdImportsBody{
			SourceUrl:      url,
			DataSourceType: int64(imp.ImportDataSourceTypeGcs),
			DataFormat:     int64(imp.ImportDataFormatCsv),
			CsvFormat:      csv,
		}
		precheckData = &models.ImportsValidateBody{
			DataFormat:     int64(imp.ImportDataFormatCsv),
			DataSourceType: int64(imp.ImportDataSourceTypeGcs),
			SourceUrl:      url,
			CheckItems:     []models.DataflowImportValidationItem{models.IMPORT_PRECHECK_DataflowImportValidationItem},
			CsvFormat:      csv,
		}
		searchImportFile = &models.ImportsSearchimportfilesBody{
			DataFormat:     int64(imp.ImportDataFormatCsv),
			DataSourceType: int64(imp.ImportDataSourceTypeGcs),
			SourceUri:      url,
		}
	}
	targetTable := &models.CommonTable{
		Schema: csvPaTable.SchemaName,
		Table:  csvPaTable.TableName,
	}
	targetTableInfo.TargetTable = targetTable
	targetTableInfo.CustomFile = ""

	if model == "TargetTable" {
		importData.TargetTableInfos = []models.DataflowImportTargetTableInfo{targetTableInfo}
		precheckData.TargetTableInfos = []models.DataflowImportTargetTableInfo{targetTableInfo}
		searchImportFile.TargetTableInfos = []models.DataflowImportTargetTableInfo{targetTableInfo}
		l4g.Info("precheckData++++++++++", precheckData.TargetTableInfos[0].TargetTable.Schema)
	}

	if t.Provider == imp.GcpProvider {
		t.DeleteCredential()
	}
	t.SetImportData(importData)
	t.SetPrecheckData(precheckData)
	t.SetSearchFileData(searchImportFile)

	// If the provider is gcp, we should create import credential each init new data set
	if t.Provider == imp.GcpProvider {
		t.CreateImportCredentialStep()
	}
}
