package service

import (
	"baron-sso-backend/internal/domain"
	"context"
	"encoding/json"
	"testing"
	"time"

	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/require"
)

type identityWriteRedisStub struct {
	values map[string]string
}

func (s *identityWriteRedisStub) Set(key string, value string, expiration time.Duration) error {
	if s.values == nil {
		s.values = map[string]string{}
	}
	s.values[key] = value
	return nil
}

func (s *identityWriteRedisStub) Get(key string) (string, error) {
	return s.values[key], nil
}

func (s *identityWriteRedisStub) Delete(key string) error {
	delete(s.values, key)
	return nil
}

func (s *identityWriteRedisStub) StoreVerificationCode(phone, code string) error {
	return nil
}

func (s *identityWriteRedisStub) GetVerificationCode(phone string) (string, error) {
	return "", nil
}

func (s *identityWriteRedisStub) DeleteVerificationCode(phone string) error {
	return nil
}

func TestIdentityWriteServiceUpdateIdentityMarksMirrorStale(t *testing.T) {
	kratos := new(MockKratosAdminServiceShared)
	redis := &identityWriteRedisStub{}
	traits := map[string]any{"email": "user@example.com"}
	kratos.On("UpdateIdentity", mock.Anything, "user-1", traits, "active").Return(&KratosIdentity{
		ID:     "user-1",
		State:  "active",
		Traits: traits,
	}, nil).Once()

	writer := NewIdentityWriteService(kratos, redis)
	updated, err := writer.UpdateIdentity(context.Background(), IdentityUpdateRequest{
		IdentityID: "user-1",
		Traits:     traits,
		State:      "active",
		Reason:     "rp_custom_claims_sync",
		Source:     "dev_handler",
	})

	require.NoError(t, err)
	require.Equal(t, "user-1", updated.ID)
	rawState := redis.values["identity:mirror:state"]
	require.NotEmpty(t, rawState)
	var state domain.IdentityCacheStatus
	require.NoError(t, json.Unmarshal([]byte(rawState), &state))
	require.Equal(t, "stale", state.Status)
	require.Contains(t, state.LastError, "rp_custom_claims_sync")
	kratos.AssertExpectations(t)
}
