package srequest_test

import (
	"encoding/json"
	"fmt"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"github.com/tech/sendico/pkg/model"
	"github.com/tech/sendico/server/interface/api/srequest"
)

func TestSignupRequest_JSONSerialization(t *testing.T) {
	signup := srequest.Signup{
		Account: model.AccountData{
			LoginData: model.LoginData{
				UserDataBase: model.UserDataBase{
					Login: "test@example.com",
				},
				Password: "TestPassword123!",
			},
			Describable: model.Describable{
				Name: "Test User",
			},
		},
		Organization: model.Describable{
			Name: "Test Organization",
		},
		OrganizationTimeZone: "UTC",
		OwnerRole: model.Describable{
			Name: "Owner",
		},
	}

	// Test JSON marshaling
	jsonData, err := json.Marshal(signup)
	require.NoError(t, err)
	assert.NotEmpty(t, jsonData)

	// Test JSON unmarshaling
	var unmarshaled srequest.Signup
	err = json.Unmarshal(jsonData, &unmarshaled)
	require.NoError(t, err)

	// Verify all fields are properly serialized/deserialized
	assert.Equal(t, signup.Account.Name, unmarshaled.Account.Name)
	assert.Equal(t, signup.Account.Login, unmarshaled.Account.Login)
	assert.Equal(t, signup.Account.Password, unmarshaled.Account.Password)
	assert.Equal(t, signup.Organization.Name, unmarshaled.Organization.Name)
	assert.Equal(t, signup.OrganizationTimeZone, unmarshaled.OrganizationTimeZone)
	assert.Equal(t, signup.OwnerRole.Name, unmarshaled.OwnerRole.Name)
}

func TestSignupRequest_MinimalValidRequest(t *testing.T) {
	signup := srequest.Signup{
		Account: model.AccountData{
			LoginData: model.LoginData{
				UserDataBase: model.UserDataBase{
					Login: "test@example.com",
				},
				Password: "TestPassword123!",
			},
			Describable: model.Describable{
				Name: "Test User",
			},
		},
		Organization: model.Describable{
			Name: "Test Organization",
		},
		OrganizationTimeZone: "UTC",
		OwnerRole: model.Describable{
			Name: "Owner",
		},
	}

	// Test JSON marshaling
	jsonData, err := json.Marshal(signup)
	require.NoError(t, err)
	assert.NotEmpty(t, jsonData)

	// Test JSON unmarshaling
	var unmarshaled srequest.Signup
	err = json.Unmarshal(jsonData, &unmarshaled)
	require.NoError(t, err)

	// Verify minimal request is valid
	assert.Equal(t, signup.Account.Name, unmarshaled.Account.Name)
	assert.Equal(t, signup.Account.Login, unmarshaled.Account.Login)
	assert.Equal(t, signup.Organization.Name, unmarshaled.Organization.Name)
}

func TestSignupRequest_InvalidJSON(t *testing.T) {
	invalidJSONs := []string{
		`{"account": invalid}`,
		`{"organization": 123}`,
		`{"organizationTimeZone": true}`,
		`{"defaultPriorityGroup": "not_an_object"}`,
		`{"anonymousUser": []}`,
		`{"anonymousRole": 456}`,
		`{invalid json}`,
	}

	for i, invalidJSON := range invalidJSONs {
		t.Run(fmt.Sprintf("Invalid JSON %d", i), func(t *testing.T) {
			var signup srequest.Signup
			err := json.Unmarshal([]byte(invalidJSON), &signup)
			require.Error(t, err)
		})
	}
}

func TestSignupRequest_UnicodeCharacters(t *testing.T) {
	signup := srequest.Signup{
		Account: model.AccountData{
			LoginData: model.LoginData{
				UserDataBase: model.UserDataBase{
					Login: "测试@example.com",
				},
				Password: "TestPassword123!",
			},
			Describable: model.Describable{
				Name: "Test 用户 Üser",
			},
		},
		Organization: model.Describable{
			Name: "测试 Organization",
		},
		OrganizationTimeZone: "UTC",
		OwnerRole: model.Describable{
			Name: "所有者",
		},
	}

	// Test JSON marshaling
	jsonData, err := json.Marshal(signup)
	require.NoError(t, err)
	assert.NotEmpty(t, jsonData)

	// Test JSON unmarshaling
	var unmarshaled srequest.Signup
	err = json.Unmarshal(jsonData, &unmarshaled)
	require.NoError(t, err)

	// Verify unicode characters are properly handled
	assert.Equal(t, "测试@example.com", unmarshaled.Account.Login)
	assert.Equal(t, "Test 用户 Üser", unmarshaled.Account.Name)
	assert.Equal(t, "测试 Organization", unmarshaled.Organization.Name)
	assert.Equal(t, "所有者", unmarshaled.OwnerRole.Name)
}
