//
//  Copyright 2026 The InfiniFlow Authors. All Rights Reserved.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

package service

import (
	"testing"

	"ragflow/internal/common"
)

// TestListMembersAuthCheck verifies that a non-owner (userID != tenantID) gets
// CodeAuthenticationError without hitting the database.
func TestListMembersAuthCheck(t *testing.T) {
	s := &TenantService{}
	_, code, err := s.ListMembers("user-abc", "tenant-xyz")
	if err == nil {
		t.Fatal("expected error for non-owner, got nil")
	}
	if code != common.CodeAuthenticationError {
		t.Errorf("expected CodeAuthenticationError, got %v", code)
	}
}

// TestAddMemberAuthCheck verifies that a non-owner gets CodeAuthenticationError.
func TestAddMemberAuthCheck(t *testing.T) {
	s := &TenantService{}
	_, code, err := s.AddMember("user-abc", "tenant-xyz", &AddMemberRequest{Email: "a@b.com"})
	if err == nil {
		t.Fatal("expected error for non-owner, got nil")
	}
	if code != common.CodeAuthenticationError {
		t.Errorf("expected CodeAuthenticationError, got %v", code)
	}
}

// TestAddMemberEmailRequired verifies the email validation runs after the auth check.
func TestAddMemberEmailRequired(t *testing.T) {
	// When userID == tenantID (owner) but no email, expect CodeArgumentError.
	s := &TenantService{}
	_, code, err := s.AddMember("owner-id", "owner-id", &AddMemberRequest{Email: ""})
	if err == nil {
		t.Fatal("expected error for empty email, got nil")
	}
	if code != common.CodeArgumentError {
		t.Errorf("expected CodeArgumentError, got %v", code)
	}
}

// TestRemoveMemberAuthCheck verifies that an unrelated user gets CodeAuthenticationError.
func TestRemoveMemberAuthCheck(t *testing.T) {
	s := &TenantService{}
	code, err := s.RemoveMember("user-abc", "tenant-xyz", "user-def")
	if err == nil {
		t.Fatal("expected error, got nil")
	}
	if code != common.CodeAuthenticationError {
		t.Errorf("expected CodeAuthenticationError, got %v", code)
	}
}

// TestRemoveMemberSelfAllowed verifies that a user removing themselves passes the auth check.
// (It will fail at the DB layer in unit tests, but the auth check must pass first.)
func TestRemoveMemberSelfAllowed(t *testing.T) {
	s := &TenantService{}
	// userID == targetUserID: auth check should pass, expect DB error (nil userTenantDAO).
	code, err := s.RemoveMember("user-abc", "tenant-xyz", "user-abc")
	if code == common.CodeAuthenticationError {
		t.Errorf("self-removal should pass auth check, got CodeAuthenticationError: %v", err)
	}
}

// TestAcceptInviteAuthCheck verifies that AcceptInvite fails when no membership exists (nil DAO).
func TestAcceptInviteAuthCheck(t *testing.T) {
	s := &TenantService{}
	// nil userTenantDAO: FilterByUserIDAndTenantID will panic/err, so we expect CodeDataError.
	code, err := s.AcceptInvite("user-abc", "tenant-xyz")
	if err == nil {
		t.Fatal("expected error when no membership exists, got nil")
	}
	if code != common.CodeDataError {
		t.Errorf("expected CodeDataError, got %v", code)
	}
}

// TestTenantRoleConstants verifies the role string values match the Python enums.
func TestTenantRoleConstants(t *testing.T) {
	cases := map[string]string{
		TenantRoleOwner:  "owner",
		TenantRoleNormal: "normal",
		TenantRoleInvite: "invite",
		TenantRoleAdmin:  "admin",
	}
	for got, want := range cases {
		if got != want {
			t.Errorf("role constant = %q, want %q", got, want)
		}
	}
}
