package directory

import (
	"context"
	"testing"

	"github.com/stretchr/testify/require"

	depmodel "security-center-backend/internal/modules/department/model"
	departmentrepo "security-center-backend/internal/modules/department/repository"
)

type fakeEmployeeRepo struct {
	employee *depmodel.Employee
}

func (f *fakeEmployeeRepo) Upsert(ctx context.Context, emp *depmodel.Employee) error { return nil }
func (f *fakeEmployeeRepo) List(ctx context.Context) ([]depmodel.Employee, error) {
	if f.employee == nil {
		return []depmodel.Employee{}, nil
	}
	return []depmodel.Employee{*f.employee}, nil
}
func (f *fakeEmployeeRepo) FindByID(ctx context.Context, id uint64) (*depmodel.Employee, error) {
	if f.employee == nil || f.employee.ID != id {
		return nil, nil
	}
	copy := *f.employee
	return &copy, nil
}
func (f *fakeEmployeeRepo) ListByDepartment(ctx context.Context, departmentID string) ([]depmodel.Employee, error) {
	if f.employee == nil || f.employee.DepartmentID != departmentID {
		return []depmodel.Employee{}, nil
	}
	return []depmodel.Employee{*f.employee}, nil
}
func (f *fakeEmployeeRepo) FindByEmail(ctx context.Context, email string) (*depmodel.Employee, error) {
	if f.employee == nil || f.employee.Email != email {
		return nil, nil
	}
	copy := *f.employee
	return &copy, nil
}
func (f *fakeEmployeeRepo) FindByEmails(ctx context.Context, emails []string) ([]depmodel.Employee, error) {
	if f.employee == nil {
		return []depmodel.Employee{}, nil
	}
	return []depmodel.Employee{*f.employee}, nil
}
func (f *fakeEmployeeRepo) Search(ctx context.Context, query string) ([]depmodel.Employee, error) {
	if f.employee == nil {
		return []depmodel.Employee{}, nil
	}
	return []depmodel.Employee{*f.employee}, nil
}

type fakeDepartmentRepo struct {
	departments []depmodel.Department
}

func (f *fakeDepartmentRepo) Upsert(ctx context.Context, dept *depmodel.Department) error { return nil }
func (f *fakeDepartmentRepo) List(ctx context.Context) ([]depmodel.Department, error) {
	return append([]depmodel.Department(nil), f.departments...), nil
}
func (f *fakeDepartmentRepo) FindByID(ctx context.Context, id uint64) (*depmodel.Department, error) {
	for i := range f.departments {
		if f.departments[i].ID == id {
			copy := f.departments[i]
			return &copy, nil
		}
	}
	return nil, nil
}
func (f *fakeDepartmentRepo) FindByLarkID(ctx context.Context, larkID string) (*depmodel.Department, error) {
	for i := range f.departments {
		if f.departments[i].LarkDepartmentID == larkID {
			copy := f.departments[i]
			return &copy, nil
		}
	}
	return nil, nil
}
func (f *fakeDepartmentRepo) ListByLarkIDs(ctx context.Context, ids []string) ([]depmodel.Department, error) {
	set := make(map[string]struct{}, len(ids))
	for _, id := range ids {
		set[id] = struct{}{}
	}
	out := make([]depmodel.Department, 0, len(f.departments))
	for _, dept := range f.departments {
		if _, ok := set[dept.LarkDepartmentID]; ok {
			out = append(out, dept)
		}
	}
	return out, nil
}

var _ departmentrepo.EmployeeRepository = (*fakeEmployeeRepo)(nil)
var _ departmentrepo.DepartmentRepository = (*fakeDepartmentRepo)(nil)

func TestRepositoryAdapterFindByEmailEnrichesDepartmentName(t *testing.T) {
	adapter := NewRepositoryAdapter(
		&fakeEmployeeRepo{employee: &depmodel.Employee{
			Base:         depmodel.Base{ID: 9},
			Name:         "Alice",
			Email:        "alice@example.com",
			DepartmentID: "dep-secops",
		}},
		&fakeDepartmentRepo{departments: []depmodel.Department{{
			Base:             depmodel.Base{ID: 7},
			Name:             "Security Operations",
			LarkDepartmentID: "dep-secops",
		}}},
	)

	employee, err := adapter.FindByEmail(context.Background(), "alice@example.com")
	require.NoError(t, err)
	require.NotNil(t, employee)
	require.Equal(t, "Security Operations", employee.DepartmentName)
}
