package oci

import (
	"strings"
	"testing"
	"time"

	"github.com/oracle/oci-go-sdk/v65/common"
	"github.com/oracle/oci-go-sdk/v65/identitydomains"
)

func TestGeneratePassword(t *testing.T) {
	for i := 0; i < 20; i++ {
		password, err := generatePassword()
		if err != nil {
			t.Fatalf("generatePassword: %v", err)
		}
		if len(password) != 16 {
			t.Fatalf("len = %d, want 16", len(password))
		}
		for _, set := range passwordCharsets {
			if !strings.ContainsAny(password, set) {
				t.Errorf("password %q missing charset %q", password, set)
			}
		}
	}
}

func TestToTenantUserDetail(t *testing.T) {
	adminRoles := &identitydomains.ExtensionUserUser{
		AppRoles: []identitydomains.UserExtAppRoles{
			{Value: common.String("r1"), Display: common.String("User Administrator")},
			{Value: common.String("r2"), Display: common.String(domainAdminRoleName)},
		},
	}
	tests := []struct {
		name string
		u    identitydomains.User
		want TenantUserDetail
	}{
		{
			name: "姓名与双管理员状态齐全",
			u: identitydomains.User{
				Name: &identitydomains.UserName{
					GivenName:  common.String("De"),
					FamilyName: common.String("Wang"),
				},
				Groups: []identitydomains.UserGroups{
					{Value: common.String("g1"), Display: common.String("Readers")},
					{Value: common.String("g2"), Display: common.String(adminGroupNames[0])},
				},
				UrnIetfParamsScimSchemasOracleIdcsExtensionUserUser: adminRoles,
			},
			want: TenantUserDetail{InDomain: true, GivenName: "De", FamilyName: "Wang", IsDomainAdmin: true, InAdminGroup: true},
		},
		{
			name: "普通成员无管理员标记",
			u: identitydomains.User{
				Name:   &identitydomains.UserName{GivenName: common.String("A"), FamilyName: common.String("B")},
				Groups: []identitydomains.UserGroups{{Value: common.String("g1"), Display: common.String("Readers")}},
			},
			want: TenantUserDetail{InDomain: true, GivenName: "A", FamilyName: "B"},
		},
		{
			name: "空档案仅置 InDomain",
			u:    identitydomains.User{},
			want: TenantUserDetail{InDomain: true},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			if got := toTenantUserDetail(tt.u); got != tt.want {
				t.Errorf("toTenantUserDetail() = %+v, want %+v", got, tt.want)
			}
		})
	}
}

func TestBuildUsageDetails(t *testing.T) {
	start := time.Date(2026, 6, 1, 0, 0, 0, 0, time.UTC)
	end := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC)
	tests := []struct {
		name    string
		q       CostQuery
		wantErr bool
	}{
		{name: "daily cost", q: CostQuery{Granularity: "DAILY", QueryType: "COST", GroupBy: "service"}},
		{name: "小写粒度可被归一化", q: CostQuery{Granularity: "monthly", QueryType: "usage", GroupBy: "skuName"}},
		{name: "非法粒度", q: CostQuery{Granularity: "HOURLY2", QueryType: "COST"}, wantErr: true},
		{name: "非法查询类型", q: CostQuery{Granularity: "DAILY", QueryType: "MONEY"}, wantErr: true},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			tt.q.StartTime, tt.q.EndTime = start, end
			details, err := buildUsageDetails("ocid1.tenancy.oc1..test", tt.q)
			if (err != nil) != tt.wantErr {
				t.Fatalf("buildUsageDetails() error = %v, wantErr %v", err, tt.wantErr)
			}
			if err != nil {
				return
			}
			if details.TenantId == nil || *details.TenantId != "ocid1.tenancy.oc1..test" {
				t.Error("tenantId not set")
			}
			if len(details.GroupBy) != 1 || details.GroupBy[0] != tt.q.GroupBy {
				t.Errorf("groupBy = %v, want [%s]", details.GroupBy, tt.q.GroupBy)
			}
		})
	}
}
