package main

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

	"direct-dev.ru/gitea/GiteaAdmin/elowdb-go/pkg/linedb"
)

func TestCustomJSONSerialization(t *testing.T) {
	// Тестируем стандартный JSON
	standardJSONMarshal := func(v any) ([]byte, error) {
		return json.Marshal(v)
	}

	standardJSONUnmarshal := func(data []byte, v any) error {
		return json.Unmarshal(data, v)
	}

	// Тестируем кастомный JSON с метаданными
	customJSONMarshal := func(v any) ([]byte, error) {
		data := map[string]any{
			"data":      v,
			"timestamp": time.Now().Unix(),
			"version":   "1.0",
		}
		return json.Marshal(data)
	}

	customJSONUnmarshal := func(data []byte, v any) error {
		var wrapper map[string]any
		if err := json.Unmarshal(data, &wrapper); err != nil {
			return err
		}

		if dataField, exists := wrapper["data"]; exists {
			dataBytes, err := json.Marshal(dataField)
			if err != nil {
				return err
			}
			return json.Unmarshal(dataBytes, v)
		}

		return json.Unmarshal(data, v)
	}

	// Тестируем функции сериализации
	testData := map[string]any{
		"id":   1,
		"name": "test",
		"age":  25,
	}

	// Тест стандартного JSON
	standardData, err := standardJSONMarshal(testData)
	if err != nil {
		t.Fatalf("Standard JSON marshal failed: %v", err)
	}

	var standardResult map[string]any
	if err := standardJSONUnmarshal(standardData, &standardResult); err != nil {
		t.Fatalf("Standard JSON unmarshal failed: %v", err)
	}

	if standardResult["name"] != "test" {
		t.Errorf("Expected 'test', got %v", standardResult["name"])
	}

	// Тест кастомного JSON
	customData, err := customJSONMarshal(testData)
	if err != nil {
		t.Fatalf("Custom JSON marshal failed: %v", err)
	}

	var customResult map[string]any
	if err := customJSONUnmarshal(customData, &customResult); err != nil {
		t.Fatalf("Custom JSON unmarshal failed: %v", err)
	}

	if customResult["name"] != "test" {
		t.Errorf("Expected 'test', got %v", customResult["name"])
	}

	fmt.Println("✓ Custom JSON serialization test passed")
}

func TestJSONLFileWithCustomSerialization(t *testing.T) {
	// Создаем функции сериализации
	customJSONMarshal := func(v any) ([]byte, error) {
		data := map[string]any{
			"data":      v,
			"timestamp": time.Now().Unix(),
			"version":   "1.0",
		}
		return json.Marshal(data)
	}

	customJSONUnmarshal := func(data []byte, v any) error {
		var wrapper map[string]any
		if err := json.Unmarshal(data, &wrapper); err != nil {
			return err
		}

		if dataField, exists := wrapper["data"]; exists {
			dataBytes, err := json.Marshal(dataField)
			if err != nil {
				return err
			}
			return json.Unmarshal(dataBytes, v)
		}

		return json.Unmarshal(data, v)
	}

	// Создаем JSONLFile с кастомными функциями
	options := linedb.JSONLFileOptions{
		CollectionName: "test",
		JSONMarshal:    customJSONMarshal,
		JSONUnmarshal:  customJSONUnmarshal,
	}

	file := linedb.NewJSONLFile("./test-custom.jsonl", "", options)

	// Инициализируем файл
	if err := file.Init(true, linedb.LineDbAdapterOptions{}); err != nil {
		t.Fatalf("Failed to init file: %v", err)
	}

	// Тестовые данные
	testData := map[string]any{
		"id":   1,
		"name": "test_user",
		"age":  25,
	}

	// Записываем данные
	if err := file.Write(testData, linedb.LineDbAdapterOptions{}); err != nil {
		t.Fatalf("Failed to write data: %v", err)
	}

	// Читаем данные
	result, err := file.Read(linedb.LineDbAdapterOptions{})
	if err != nil {
		t.Fatalf("Failed to read data: %v", err)
	}

	if len(result) != 1 {
		t.Fatalf("Expected 1 record, got %d", len(result))
	}

	if record, ok := result[0].(map[string]any); ok {
		if record["name"] != "test_user" {
			t.Errorf("Expected 'test_user', got %v", record["name"])
		}
	} else {
		t.Fatal("Failed to cast result to map")
	}

	fmt.Println("✓ JSONLFile with custom serialization test passed")
}
