package mysql

import (
	"context"
	"testing"

	"wucher/internal/domain/auth"
	"wucher/internal/domain/user"
	"wucher/internal/shared/pkg/uuidv7"
)

func TestUserRepository_SyncsAndLoadsUserRoles(t *testing.T) {
	db := openDBTestSQLite(t)
	if err := AutoMigrate(db); err != nil {
		t.Fatalf("auto migrate: %v", err)
	}

	pilotRoleID := uuidv7.MustBytes()
	chiefPilotRoleID := uuidv7.MustBytes()
	staffRoleID := uuidv7.MustBytes()
	roles := []auth.Role{
		{ID: pilotRoleID, Code: "pilot", Name: "pilot", Description: "Pilot"},
		{ID: chiefPilotRoleID, Code: "chief_pilot", Name: "chief_pilot", Description: "Chief Pilot"},
		{ID: staffRoleID, Code: "staff", Name: "staff", Description: "Staff"},
	}
	if err := db.Create(&roles).Error; err != nil {
		t.Fatalf("create roles: %v", err)
	}

	repo := NewUserRepository(db)
	ctx := context.Background()
	u := &user.User{
		Email:     "multi-role@example.com",
		Username:  "multi.role",
		FirstName: "Multi",
		LastName:  "Role",
		Timezone:  "UTC",
		RoleID:    pilotRoleID,
		RoleIDs:   [][]byte{pilotRoleID, chiefPilotRoleID},
	}
	if err := repo.Create(ctx, u); err != nil {
		t.Fatalf("create user: %v", err)
	}

	var count int64
	if err := db.Model(&auth.UserRole{}).Where("user_id = ?", u.ID).Count(&count).Error; err != nil {
		t.Fatalf("count user_roles: %v", err)
	}
	if count != 2 {
		t.Fatalf("expected 2 user_roles rows, got %d", count)
	}

	got, err := repo.GetByID(ctx, u.ID)
	if err != nil {
		t.Fatalf("get by id: %v", err)
	}
	if got == nil {
		t.Fatalf("expected user")
	}
	if len(got.RoleIDs) != 2 || len(got.Roles) != 2 {
		t.Fatalf("expected two roles loaded, got roleIDs=%d roles=%d", len(got.RoleIDs), len(got.Roles))
	}
	if got.Roles[0].Name != "pilot" {
		t.Fatalf("expected primary role first, got %q", got.Roles[0].Name)
	}

	list, total, err := repo.List(ctx, "", "", 10, 0)
	if err != nil {
		t.Fatalf("list users: %v", err)
	}
	if total != 1 || len(list) != 1 || len(list[0].Roles) != 2 {
		t.Fatalf("expected list to include two roles, total=%d len=%d roles=%d", total, len(list), len(list[0].Roles))
	}

	got.RoleID = staffRoleID
	got.RoleIDs = [][]byte{staffRoleID}
	if err := repo.Update(ctx, got); err != nil {
		t.Fatalf("update user roles: %v", err)
	}

	got, err = repo.GetByID(ctx, u.ID)
	if err != nil {
		t.Fatalf("get by id after update: %v", err)
	}
	if got == nil {
		t.Fatalf("expected user after update")
	}
	if len(got.Roles) != 1 || got.Roles[0].Name != "staff" {
		t.Fatalf("expected roles replaced with staff, got %+v", got.Roles)
	}

	if err := repo.Delete(ctx, u.ID); err != nil {
		t.Fatalf("delete user: %v", err)
	}
	if err := db.Model(&auth.UserRole{}).Where("user_id = ?", u.ID).Count(&count).Error; err != nil {
		t.Fatalf("count user_roles after delete: %v", err)
	}
	if count != 0 {
		t.Fatalf("expected user_roles deleted, got %d", count)
	}
}
