package api

import "encoding/json"

// msp
type OpenApiMspCustomer struct {
	//The ID of the MSP customer.
	ID string `json:"id" example:"123456"`
	//The ID of the MSP customer.
	OrgID string `json:"orgId" example:"123456"`
	//The email of the MSP customer.
	Email string `json:"email" example:"123@my.com"`
	//The org name of the MSP customer.
	OrgName string `json:"orgName" example:"New Org"`
	//The state of the MSP customer.
	State string `json:"state" example:"active"`
	//The effected time of the MSP customer.
	EffectedTime string `json:"effectedTime" example:"2023-12-06 15:18:13"`
	//The expired time of the MSP customer.
	ExpiredTime string `json:"expiredTime" example:"2023-12-06 15:18:13"`
}

type OpenApiCreateMspCustomerSignupUrlReq struct {
	//The ID of the MSP.
	OrgID string `json:"orgId" example:"123456"`
}

type OpenApiMspCustomerSignupUrl struct {
	//The signup URL of the MSP customer.
	CustomerSignupUrl string `json:"customerSignupUrl" example:"https://test.com/signup?msp=test&third_party_account_provider=test&third_party_account_token=test"`
	//The expired time of the MSP customer signup url.
	ExpiredAt string `json:"expiredAt" example:"2024-12-06 15:18:13"`
}

type OpenApiMspCustomerOrgID struct {
	CustomerOrgId uint64 `uri:"customerOrgId" json:"customerOrgId"`
}

type OpenApiCreateApiKeyReq struct {
	//The display name of API key.
	DisplayName string `json:"displayName" example:"New Key"`
	//The role of API key. If the projectId is set to 0, the role should be Organization roles, if the projectId is not set to 0, the role should be Project roles.
	//
	//Organization roles:
	//- `org:owner`: indicates the 'Organization Owner' role.
	//- `org:member`: indicates the 'Organization Viewer'.
	//- `org:billing_admin`: indicates the 'Organization Billing Manager' role.
	//- `org:billing_viewer`: indicates the 'Organization Billing Viewer' role.
	//- `org:audit_admin`: indicates the 'Organization Console Audit Manager' role.
	//
	//Project roles:
	//- `project:owner`: indicates the 'Project Owner' role.
	//- `project:dev`: indicates the 'Project Data Access Read-Write' role.
	//- `project:readonly`: indicates the 'Project Data Access Read-Only' role.
	//- `project:ctl_plane_viewer`: indicates the 'Project Viewer' role.
	Role string `json:"role" example:"org:owner"`
	//The project to which the API key belongs. If not set, the API key belongs to org.
	ProjectId uint64 `json:"projectId" example:"123456"`
}

type OpenApiUpdateApiKeyReq struct {
	//The display name of the API key.
	DisplayName string `json:"displayName" example:"New Key"`
	//The role of API key. If the projectId is set to 0, the role should be Organization roles, if the projectId is not set to 0, the role should be Project roles.
	//
	//Organization roles:
	//- `org:owner`: indicates the 'Organization Owner' role.
	//- `org:member`: indicates the 'Organization Viewer'.
	//- `org:billing_admin`: indicates the 'Organization Billing Manager' role.
	//- `org:billing_viewer`: indicates the 'Organization Billing Viewer' role.
	//- `org:audit_admin`: indicates the 'Organization Console Audit Manager' role.
	//
	//Project roles:
	//- `project:owner`: indicates the 'Project Owner' role.
	//- `project:dev`: indicates the 'Project Data Access Read-Write' role.
	//- `project:readonly`: indicates the 'Project Data Access Read-Only' role.
	//- `project:ctl_plane_viewer`: indicates the 'Project Viewer' role.
	Role string `json:"role" example:"org:owner"`
	//The project to which the API key belongs. If not set, the API key belongs to org.
	ProjectId uint64 `json:"projectId" example:"123456"`
}

type OpenApiApiKey struct {
	//The name of the API key.
	Name string `json:"name" example:"orgs/1/apiKeys/2"`
	//The access key of the API key.
	AccessKey string `json:"accessKey" example:"ABCDEFGH"`
	//The secret key of the API key.
	SecretKey string `json:"secretKey" example:"498c7f44-656f-4944-b455-0695faa5d4f9"`
	//The display name of the API key.
	DisplayName string `json:"displayName" example:"New Key"`
	//The role of the API key.
	Role string `json:"role" example:"org:owner"`
}

type OpenApiAccessKey struct {
	//The access key of the API key.
	AccessKey string `uri:"accessKey" json:"accessKey" example:"ABCDEFGH"`
}

type OpenApiListApiKeyRsp struct {
	// The list of matching API keys.
	ApiKeys []OpenApiApiKey `json:"apiKeys"`
	// `nextPageToken` A token, which can be sent as `pageToken` to retrieve the next page. If this field is omitted, there are no subsequent pages.
	NextPageToken string `json:"nextPageToken" example:"498c7f44-656f-4944-b455-0695faa5d4f9"`
}

type OpenApiListApiKeyRolesRsp struct {
	// The Org roles that API key supports.
	OrgRoles []string `json:"orgRoles"`
	// The Project roles that API key supports.
	ProjectRoles []string `json:"projectRoles"`
}

type OpenApiListApiKeysPageReq struct {
	// A page size, the size of one page
	PageSize          int32 `form:"pageSize" example:"5"`
	PageSizeUnderline int32 `form:"page_size" example:"5"`
	// A page token, received from a previous `ListApiKeys` call.
	PageToken          string `form:"pageToken" example:"498c7f44-656f-4944-b455-0695faa5d4f9"`
	PageTokenUnderline string `form:"page_token" example:"498c7f44-656f-4944-b455-0695faa5d4f9"`
	// The project to which returned API key belongs. If not set, return the API keys belongs to org.
	ProjectId uint64 `form:"projectId" example:"123456"`
}

type OpenApiPageReq struct {
	// A page size, the size of one page.
	PageSize          int32 `form:"pageSize" example:"5"`
	PageSizeUnderline int32 `form:"page_size" example:"5"`
	// A page token, received from a previous `ListApiKeys` call.
	PageToken          string `form:"pageToken" example:"498c7f44-656f-4944-b455-0695faa5d4f9"`
	PageTokenUnderline string `form:"page_token" example:"498c7f44-656f-4944-b455-0695faa5d4f9"`
}

type OpenApiUpdateApiKeyRoleReq struct {
	Description  string              `json:"description" example:"New Key"`
	OrgRole      string              `json:"orgRole" example:"New Key"`
	ProjectRoles []OpenApiApiKeyRole `json:"projectRoles" example:"org:owner"`
	ClusterRoles []OpenApiApiKeyRole `json:"clusterRoles" example:"org:owner"`
}

type OpenApiApiKeyRole struct {
	ScopeIdStr string `json:"scopeIdStr" example:"123456"`
	ScopeId    uint64 `json:"scopeId" example:"123456"`
	Role       string `json:"role" example:"project:dev"`
}

type OpenApiError struct {
	error
	// Error code
	Code string `json:"code"`
	// HTTP status code
	Status int `json:"status"`
	// Error message prefix
	MsgPrefix string `json:"msgPrefix"`
}

// sqluser
type ListSqlUserReq struct {
	OrgId     uint64
	ProjectId uint64
	ClusterId uint64
}
type PageReq struct {
	PageSize uint32 `form:"page_size" example:"5"`
	Page     uint32 `form:"page" example:"5"`
	//PageSize uint32 `json:"page_size" example:"5"`
	//Page     uint32 `json:"page" example:"5"`
}

type SqlUserUriReq struct {
	ClusterId uint64 `uri:"clusterId" binding:"required"`
	UserName  string `uri:"userName"`
}

type GetDbuserRsp struct {
	// JWT to connect to the cluster
	Jwt string `json:"jwt"`
	// The username connect to the cluster
	DbUser string `json:"dbuser"`
}

type SqlUser struct {
	UserName    string   `json:"userName"`
	BuiltinRole string   `json:"builtinRole"`
	AuthMethod  string   `json:"authMethod"`
	CustomRoles []string `json:"customRoles,omitempty"`
}

type UserInfo struct {
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	Email     string `json:"email"`
	Username  string `json:"username"`
}
type CreateSqlUserReq struct {
	//The username of the sql user, if cluster is serverless and autoPrefix is false, the userName must be start with serverless token.
	UserName string `json:"userName"`
	Password string `json:"password"`
	//The builtinRole of the sql user,available values [role_admin,role_readonly,role_readwrite] . if cluster is serverless and autoPrefix is false, the builtinRole[role_readonly,role_readwrite] must be start with serverless token.
	BuiltinRole string `json:"builtinRole"`
	//available values [mysql_native_password] .
	AuthMethod string `json:"authMethod"`
	// if cluster is serverless ,customRoles roles do not need to be prefixed.
	CustomRoles []string `json:"customRoles"`
	// if autoPrefix is true ,username and  builtinRole will automatically add the serverless token prefix.
	AutoPrefix bool `json:"autoPrefix"`
}
type UpdateSqlUserReq struct {
	Password    string   `json:"password"`
	BuiltinRole string   `json:"builtinRole"`
	CustomRoles []string `json:"customRoles"`
}

//type GetSqlUserRsp struct {
//	// JWT to connect to the cluster
//	Jwt string `json:"jwt"`
//	// The username connect to the cluster
//	DbUser string `json:"dbuser"`
//}

type QuerySqlUserReq struct {
	UserNames   []string `form:"userNames" example:"test"`
	AuthMethods []string `form:"authMethods" example:"mysql_native_password"`
}

type DeleteSqlUserReq struct {
	// name of the sqluser
	UserName string `json:"userName" example:"test"`
}

type ListSqlUsersRsp struct {
	//SqlUsers []*SqlUser `json:"sqlUsers"`
	SqlUsers []SqlUser `json:"sqlUsers"`
	// `next_page_token` can be sent in a subsequent call to fetch more results
	NextPageToken string `json:"nextPageToken" example:"498c7f44-656f-4944-b455-0695faa5d4f9"`
}

type ListProjectsRsp struct {
	// The list of matching Projects.
	Projects []Project `json:"projects"`

	// `nextPageToken` A token, which can be sent as `pageToken` to retrieve the next page. If this field is omitted, there are no subsequent pages.
	NextPageToken string `json:"nextPageToken" example:"498c7f44-656f-4944-b455-0695faa5d4f9"`
}

type ListProjectsReq struct {

	// A page size, the size of one page
	PageSize uint32 `form:"page_size" example:"5"`
	// A page token, received from a previous `ListApiKeys` call.
	Page uint32 `form:"page" example:"1"`
}

//type ListProjectsRsp struct {
//	// The list of project
//	Items []*Project `json:"items"`
//	// total records
//	Total uint32 `json:"total" example:"20"`
//}

type Project struct {
	//The id of the project.
	Id string `json:"id" example:"1234566"`
	//The name of the API key.
	Name string `json:"name" example:"project01"`
	//The create time of the project in ISODate string. e.g. '2025-07-16T08:31:29.194Z'
	CreateTime string `json:"createTime" example:"2025-07-16T08:31:29.194Z"`
	//Indicates whether the CMEK (Customer-Managed Encryption Keys) is enabled in this project.
	CmekEnabled bool `json:"cmekEnabled" example:"true"`
	//The org id of the project. `Deprecated`. the field will be removed later.
	OrgId string `json:"org_id" example:"324234234"`
	//The create time key of the project. `Deprecated`. the field will be removed later and will be replaced by createTime
	CreateTimestamp string `json:"create_timestamp" example:"1688460316"`
	//Number of users in the project. `Deprecated`. the field will be removed later.
	UserCount uint64 `json:"user_count" example:"4"`
	//Number of cluster_ in the project. `Deprecated`. the field will be removed later.
	ClusterCount int64 `json:"cluster_count" example:"7"`
	//The AwsCmekEnabled of the project. `Deprecated`. the field will be removed later and will be replaced by cmekEnabled
	AwsCmekEnabled bool `json:"aws_cmek_enabled" example:"false"`
	// The type of the project.
	Type string `json:"type" example:"dedicated"`
}

type CreateProjectReq struct {
	// the name of project
	Name string `form:"name" example:"test"`
	// the AwsCmekEnabled of project
	AwsCmekEnabled bool `form:"aws_cmek_enabled"  example:"false"`
}

type CreateProjectResp struct {
	// the id of project
	Id uint64 `form:"id" example:"133443"`
}

type BasicResp struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

// Users OpenAPI v1beta1 request/response structs

type OpenApiUserRole struct {
	// Scope ID
	ScopeId string `json:"scopeId"`
	// RBAC role
	RbacRole string `json:"rbacRole"`
}

type OpenApiOrgRole struct {
	// Organization ID
	ScopeId string `json:"scopeId"`
	// Organization role
	RbacRole string `json:"rbacRole" example:"org:owner" enums:"org:owner,org:member,org:billing_admin,org:billing_viewer,org:audit_admin"`
}

type OpenApiProjectRole struct {
	// Project ID
	ScopeId string `json:"scopeId"`
	// Project role
	RbacRole string `json:"rbacRole" example:"project:owner" enums:"project:owner,project:dev,project:readonly,project:ctl_plane_viewer"`
}

type OpenApiInstanceRole struct {
	// Instance ID
	ScopeId string `json:"scopeId"`
	// Instance role
	RbacRole string `json:"rbacRole" example:"cluster:admin" enums:"cluster:admin,cluster:viewer"`
}

func convertProjectRoles(roles []OpenApiProjectRole) []OpenApiUserRole {
	result := make([]OpenApiUserRole, len(roles))
	for i, r := range roles {
		result[i] = OpenApiUserRole(r)
	}
	return result
}

func convertInstanceRoles(roles []OpenApiInstanceRole) []OpenApiUserRole {
	result := make([]OpenApiUserRole, len(roles))
	for i, r := range roles {
		result[i] = OpenApiUserRole(r)
	}
	return result
}

type OpenApiListUsersReq struct {
	PageSize   int32    `form:"pageSize"`
	PageToken  string   `form:"pageToken"`
	Email      string   `form:"email"`
	Roles      []string `form:"roles"`
	Statuses   []string `form:"statuses"`
	OrderBy    string   `form:"orderBy"`
	ProjectId  string   `form:"projectId"`
	InstanceId string   `form:"instanceId"`
}

type OpenApiListUsersRsp struct {
	// List of users
	Users []OpenApiUser `json:"users"`
	// Token to retrieve the next page of results
	NextPageToken string `json:"nextPageToken" example:""`
	// Total number of users matching the query
	TotalSize int32 `json:"totalSize" example:"10"`
}

type OpenApiUser struct {
	// Unique identifier of the user
	UserId string `json:"userId" example:"123456"`
	// Email address of the user
	Email string `json:"email" example:"user@example.com"`
	// First name of the user
	FirstName string `json:"firstName" example:"John"`
	// Last name of the user
	LastName string `json:"lastName" example:"Doe"`
	// Status of the user
	Status string `json:"status" example:"active"`
	// Organization role of the user
	OrgRole *OpenApiOrgRole `json:"orgRole,omitempty"`
	// Project roles of the user
	ProjectRoles []OpenApiProjectRole `json:"projectRoles,omitempty"`
	// Instance roles of the user
	InstanceRoles []OpenApiInstanceRole `json:"instanceRoles,omitempty"`
	// Time when the user was invited
	InviteTime string `json:"inviteTime,omitempty" example:"2024-01-01T00:00:00Z"`
	// Time when the user last logged in
	LastLoginTime string `json:"lastLoginTime,omitempty" example:"2024-01-01T00:00:00Z"`
}

type OpenApiInviteUsersReq struct {
	// Email addresses of the users to invite
	Emails []string `json:"emails" validate:"required"`
	// Organization role to assign to the invited users
	OrgRole *OpenApiOrgRole `json:"orgRole" validate:"required"`
	// Project roles to assign to the invited users
	ProjectRoles []OpenApiProjectRole `json:"projectRoles,omitempty"`
	// Instance roles to assign to the invited users
	InstanceRoles []OpenApiInstanceRole `json:"instanceRoles,omitempty"`
}

type OpenApiInviteUsersRsp struct {
	// List of invited user results
	Users []OpenApiInviteUserResult `json:"users"`
	// Whether the invitation was successful
	Success bool `json:"success"`
	// Response message
	Message string `json:"message"`
}

type OpenApiInviteUserResult struct {
	// Unique identifier of the invited user
	UserId string `json:"userId"`
	// Email address of the invited user
	Email string `json:"email"`
}

type OpenApiUpdateUserReq struct {
	OrgRole       *OpenApiUserRole                `json:"orgRole,omitempty"`
	ProjectRoles  *OptionalArray[OpenApiUserRole] `json:"projectRoles,omitempty"`
	InstanceRoles *OptionalArray[OpenApiUserRole] `json:"instanceRoles,omitempty"`
}

type OpenApiBatchUpdateUsersReq struct {
	Users []OpenApiBatchUpdateUserEntry `json:"users"`
}

type OpenApiBatchUpdateUserEntry struct {
	UserId        string                          `json:"userId"`
	OrgRole       *OpenApiUserRole                `json:"orgRole,omitempty"`
	ProjectRoles  *OptionalArray[OpenApiUserRole] `json:"projectRoles,omitempty"`
	InstanceRoles *OptionalArray[OpenApiUserRole] `json:"instanceRoles,omitempty"`
}

type OpenApiBatchUpdateUsersRsp struct {
	// List of batch update results
	Results []OpenApiBatchUpdateUserResult `json:"results"`
}

type OpenApiBatchUpdateUserResult struct {
	// Unique identifier of the user
	UserId string `json:"userId"`
	// Whether the update was successful
	Success bool `json:"success"`
	// Error details if the update failed
	Error *OpenApiBatchUpdateError `json:"error,omitempty"`
}

type OpenApiBatchUpdateError struct {
	// Error code
	Code string `json:"code"`
	// Error message
	Message string `json:"message"`
}

type OpenApiUserIdReq struct {
	UserId string `uri:"user_id"`
}

type OptionalArray[T any] struct {
	IsSet bool
	Value []T
}

func (o *OptionalArray[T]) UnmarshalJSON(data []byte) error {
	o.IsSet = true

	if string(data) == "[]" {
		o.Value = []T{}
		return nil
	}

	var arr []T
	if err := json.Unmarshal(data, &arr); err != nil {
		return err
	}
	o.Value = arr
	return nil
}

type openApiUpdateUserReqDoc struct {
	// Organization role to update
	OrgRole *OpenApiOrgRole `json:"orgRole,omitempty"`
	// Project roles to update
	ProjectRoles []OpenApiProjectRole `json:"projectRoles,omitempty"`
	// Instance roles to update
	InstanceRoles []OpenApiInstanceRole `json:"instanceRoles,omitempty"`
}

type openApiBatchUpdateUsersReqDoc struct {
	// List of users to update
	Users []openApiBatchUpdateUserEntryDoc `json:"users"`
}

type openApiBatchUpdateUserEntryDoc struct {
	// Unique identifier of the user
	UserId string `json:"userId" validate:"required"`
	// Organization role to update
	OrgRole *OpenApiOrgRole `json:"orgRole,omitempty"`
	// Project roles to update
	ProjectRoles []OpenApiProjectRole `json:"projectRoles,omitempty"`
	// Instance roles to update
	InstanceRoles []OpenApiInstanceRole `json:"instanceRoles,omitempty"`
}
