package vercel

import (
	"database/sql"
	"math/rand"
	"strconv"

	"github.com/pingcap/errors"
	vercelProxy "github.com/tidbcloud/ecosystem-service/internal/service/proxy/vercel"
	vercelDB "github.com/tidbcloud/ecosystem-service/internal/storage/db/vercel"
)

func randomString(n int) string {
	var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")

	s := make([]rune, n)
	for i := range s {
		s[i] = letters[rand.Intn(len(letters))]
	}
	return string(s)
}

func transferToIdentifierEntity(res []vercelProxy.EnvironmentInfo) (*vercelDB.EnvironmentIdentifier, error) {
	identifier := vercelDB.EnvironmentIdentifier{}
	for _, elem := range res {
		if elem.Key == "TIDB_HOST" {
			identifier.TiDBHostID = sql.NullString{
				String: elem.ID,
				Valid:  true,
			}
		} else if elem.Key == "TIDB_PORT" {
			identifier.TiDBPortID = sql.NullString{
				String: elem.ID,
				Valid:  true,
			}
		} else if elem.Key == "TIDB_USER" {
			identifier.TiDBUserID = sql.NullString{
				String: elem.ID,
				Valid:  true,
			}
		} else if elem.Key == "TIDB_PASSWORD" {
			identifier.TiDBPasswordID = sql.NullString{
				String: elem.ID,
				Valid:  true,
			}
		} else if elem.Key == "TIDB_SSL_CA" {
			identifier.TiDBSslCaID = sql.NullString{
				String: elem.ID,
				Valid:  true,
			}
		} else if elem.Key == "TIDB_DATABASE" {
			identifier.TiDBDatabaseID = sql.NullString{
				String: elem.ID,
				Valid:  true,
			}

		} else if elem.Key == "DATABASE_URL" {
			identifier.DatabaseUrlID = sql.NullString{
				String: elem.ID,
				Valid:  true,
			}
		} else {
			return nil, errors.Errorf("Unknown environment variable, key: %s", elem.Key)
		}
	}
	return &identifier, nil
}

func transferToDataAppIdentifierEntity(res []vercelProxy.EnvironmentInfo) (*vercelDB.DataAppEnvironmentIdentifier, error) {
	identifier := vercelDB.DataAppEnvironmentIdentifier{}
	for _, elem := range res {
		if elem.Key == envDataAppBaseUrl {
			identifier.DataAppBaseUrl = sql.NullString{
				String: elem.ID,
				Valid:  true,
			}
		} else if elem.Key == envDataAppPublicKey {
			identifier.DataAppPublicKey = sql.NullString{
				String: elem.ID,
				Valid:  true,
			}
		} else if elem.Key == envDataAppPrivateKey {
			identifier.DataAppPrivateKey = sql.NullString{
				String: elem.ID,
				Valid:  true,
			}
		} else {
			return nil, errors.Errorf("Unknown environment variable, key: %s", elem.Key)
		}
	}
	return &identifier, nil
}

func parseUintIDForTiDBCluster(path TiDBCluster) (uint64, uint64, uint64, error) {
	orgID, err := strconv.ParseUint(path.TiDBOrgID, 10, 64)
	if err != nil {
		return 0, 0, 0, errors.Trace(err)
	}

	projectID, err := strconv.ParseUint(path.TiDBProjectID, 10, 64)
	if err != nil {
		return orgID, 0, 0, errors.Trace(err)
	}

	clusterID, err := strconv.ParseUint(path.TiDBClusterID, 10, 64)
	if err != nil {
		return orgID, projectID, 0, errors.Trace(err)
	}
	return orgID, projectID, clusterID, nil
}

func parseUintIDForDataApp(path DataAppPath) (uint64, uint64, uint64, error) {
	orgID, err := strconv.ParseUint(path.TiDBOrgID, 10, 64)
	if err != nil {
		return 0, 0, 0, errors.Trace(err)
	}

	projectID, err := strconv.ParseUint(path.TiDBProjectID, 10, 64)
	if err != nil {
		return orgID, 0, 0, errors.Trace(err)
	}

	dataAppID, err := strconv.ParseUint(path.DataAppID, 10, 64)
	if err != nil {
		return orgID, 0, 0, errors.Trace(err)
	}

	return orgID, projectID, dataAppID, nil
}

func parseUintIDForTiDBProject(path TiDBProject) (uint64, uint64, error) {
	orgID, err := strconv.ParseUint(path.TiDBOrgID, 10, 64)
	if err != nil {
		return 0, 0, errors.Trace(err)
	}

	projectID, err := strconv.ParseUint(path.TiDBProjectID, 10, 64)
	if err != nil {
		return orgID, 0, errors.Trace(err)
	}

	return orgID, projectID, nil
}

func convertToProjectResp(integrationConfiguration *vercelProxy.RetrieveIntegrationConfigurationResponse, projectsResponse []vercelProxy.Project) RetrieveProjectResponse {
	projectsVOResponse := RetrieveProjectResponse{}
	if integrationConfiguration.AllowedProjectIDs != nil {
		var allowedProjects []ProjectVO
		projectMap := make(map[string]*vercelProxy.Project)

		for i, project := range projectsResponse {
			projectMap[project.ID] = &projectsResponse[i]
		}
		for _, projectID := range integrationConfiguration.AllowedProjectIDs {
			allowedProjects = append(allowedProjects, ProjectVO{
				ID:   (*projectMap[projectID]).ID,
				Name: (*projectMap[projectID]).Name,
			})
		}

		projectsVOResponse.Projects = allowedProjects
	} else {
		projectsVOResponse.Projects = make([]ProjectVO, len(projectsResponse))
		for i, project := range projectsResponse {
			projectsVOResponse.Projects[i] = ProjectVO{
				ID:   project.ID,
				Name: project.Name,
			}
		}
	}
	return projectsVOResponse
}
