package main

import (
	"baron-sso-backend/internal/service"
	"context"
	"strings"
	"testing"
)

func TestResolveCreateSuperAdminConfigUsesEnvDefaults(t *testing.T) {
	t.Setenv("ADMIN_EMAIL", "admin@example.com")
	t.Setenv("ADMIN_PASSWORD", "Password!123")
	t.Setenv("ADMIN_NAME", "Env Admin")

	config, err := resolveCreateSuperAdminConfig([]string{})
	if err != nil {
		t.Fatalf("resolveCreateSuperAdminConfig returned error: %v", err)
	}

	if config.Email != "admin@example.com" {
		t.Fatalf("email = %q", config.Email)
	}
	if config.Password != "Password!123" {
		t.Fatal("password was not read from ADMIN_PASSWORD")
	}
	if config.Name != "Env Admin" {
		t.Fatalf("name = %q", config.Name)
	}
}

func TestResolveCreateSuperAdminConfigAllowsFlagOverrides(t *testing.T) {
	t.Setenv("ADMIN_EMAIL", "admin@example.com")
	t.Setenv("ADMIN_PASSWORD", "Password!123")
	t.Setenv("ADMIN_NAME", "Env Admin")

	config, err := resolveCreateSuperAdminConfig([]string{
		"--email", "flag@example.com",
		"--password", "FlagPassword!123",
		"--name", "Flag Admin",
		"--update-password",
	})
	if err != nil {
		t.Fatalf("resolveCreateSuperAdminConfig returned error: %v", err)
	}

	if config.Email != "flag@example.com" {
		t.Fatalf("email = %q", config.Email)
	}
	if config.Password != "FlagPassword!123" {
		t.Fatal("password flag was not used")
	}
	if config.Name != "Flag Admin" {
		t.Fatalf("name = %q", config.Name)
	}
	if !config.UpdatePassword {
		t.Fatal("update password flag was not set")
	}
}

func TestResolveCreateSuperAdminConfigRequiresEmailAndPassword(t *testing.T) {
	t.Setenv("ADMIN_EMAIL", "")
	t.Setenv("ADMIN_PASSWORD", "")

	if _, err := resolveCreateSuperAdminConfig([]string{}); err == nil {
		t.Fatal("expected error")
	}
}

func TestResolveClearOrphanUserTenantMembershipsConfig(t *testing.T) {
	config, err := resolveClearOrphanUserTenantMembershipsConfig([]string{"--dry-run"})
	if err != nil {
		t.Fatalf("resolveClearOrphanUserTenantMembershipsConfig returned error: %v", err)
	}

	if !config.DryRun {
		t.Fatal("dry-run flag was not set")
	}
}

func TestAuditWorksmobileDuplicatePhoneCountryCodesReportsAndFixes(t *testing.T) {
	client := &fakeWorksmobilePhoneAuditClient{
		users: []service.WorksmobileRemoteUser{
			{
				ID:          "works-user-1",
				ExternalID:  "baron-user-1",
				Email:       "one@example.com",
				DisplayName: "One",
				CellPhone:   "+82 +821091917771",
				DomainID:    1001,
				DomainName:  "samaneng.com",
			},
			{
				ID:        "works-user-2",
				Email:     "two@example.com",
				CellPhone: "+821012345678",
				DomainID:  1001,
			},
		},
	}
	output := &strings.Builder{}

	count, err := auditWorksmobileDuplicatePhoneCountryCodes(context.Background(), output, true, client)
	if err != nil {
		t.Fatalf("auditWorksmobileDuplicatePhoneCountryCodes returned error: %v", err)
	}
	if count != 1 {
		t.Fatalf("count=%d, want 1", count)
	}
	if !strings.Contains(output.String(), "one@example.com") || !strings.Contains(output.String(), "+821091917771") {
		t.Fatalf("audit output did not include normalized duplicate phone row: %s", output.String())
	}
	if len(client.patches) != 1 {
		t.Fatalf("patch count=%d, want 1", len(client.patches))
	}
	if client.patches[0].identifier != "works-user-1" {
		t.Fatalf("patch identifier=%q, want works-user-1", client.patches[0].identifier)
	}
	if client.patches[0].payload.CellPhone != "+821091917771" {
		t.Fatalf("patch cellPhone=%q, want +821091917771", client.patches[0].payload.CellPhone)
	}
}

type fakeWorksmobilePhoneAuditClient struct {
	users   []service.WorksmobileRemoteUser
	patches []fakeWorksmobilePhonePatch
}

type fakeWorksmobilePhonePatch struct {
	identifier string
	payload    service.WorksmobileUserPatchPayload
}

func (f *fakeWorksmobilePhoneAuditClient) ListUsers(ctx context.Context) ([]service.WorksmobileRemoteUser, error) {
	return f.users, nil
}

func (f *fakeWorksmobilePhoneAuditClient) PatchUser(ctx context.Context, identifier string, payload service.WorksmobileUserPatchPayload) error {
	f.patches = append(f.patches, fakeWorksmobilePhonePatch{identifier: identifier, payload: payload})
	return nil
}
