package main

import (
	"fmt"
	"log"
	"time"

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

// testDeleteOneRecordByID тестирует удаление одной записи по ID
func testDeleteOneRecordByID() {
	// Создаем базу данных
	db := linedb.NewLineDb(nil)

	// Инициализируем базу данных
	initOptions := &linedb.LineDbInitOptions{
		CacheSize: 1000,
		CacheTTL:  10 * time.Second,
		DBFolder:  "./data/test-linedb-delete",
		Collections: []linedb.JSONLFileOptions{
			{
				CollectionName: "users",
				AllocSize:      256,
				IndexedFields:  []string{"id", "username"},
			},
		},
	}

	if err := db.Init(true, initOptions); err != nil {
		log.Printf("Failed to init database: %v", err)
		return
	}
	defer db.Close()

	// Создаем тестовые данные
	user := map[string]any{
		"id":       1,
		"username": "test_user",
		"email":    "test@example.com",
		"isActive": true,
	}

	// Вставляем данные
	if err := db.Insert(user, "users", linedb.LineDbAdapterOptions{}); err != nil {
		log.Printf("Failed to insert user: %v", err)
		return
	}

	// Читаем данные
	users, err := db.Read("users", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read users: %v", err)
		return
	}
	fmt.Printf("   Записей до удаления: %d\n", len(users))

	// Удаляем запись по ID
	deleted, err := db.Delete(map[string]any{"id": 1}, "users", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to delete user: %v", err)
		return
	}
	fmt.Printf("   Удалено записей: %d\n", len(deleted))

	// Проверяем результат
	users, err = db.Read("users", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read users after delete: %v", err)
		return
	}
	fmt.Printf("   Записей после удаления: %d\n", len(users))
}

// testDeleteOneRecordByTextFilter тестирует удаление одной записи по текстовому фильтру
func testDeleteOneRecordByTextFilter() {
	// Создаем базу данных
	db := linedb.NewLineDb(nil)

	// Инициализируем базу данных
	initOptions := &linedb.LineDbInitOptions{
		CacheSize: 1000,
		CacheTTL:  10 * time.Second,
		DBFolder:  "./data/test-linedb-delete",
		Collections: []linedb.JSONLFileOptions{
			{
				CollectionName: "products",
				AllocSize:      256,
				IndexedFields:  []string{"id", "name"},
			},
		},
	}

	if err := db.Init(true, initOptions); err != nil {
		log.Printf("Failed to init database: %v", err)
		return
	}
	defer db.Close()

	// Создаем тестовые данные
	product := map[string]any{
		"id":       1,
		"name":     "Test Product",
		"price":    99.99,
		"category": "Electronics",
	}

	// Вставляем данные
	if err := db.Insert(product, "products", linedb.LineDbAdapterOptions{}); err != nil {
		log.Printf("Failed to insert product: %v", err)
		return
	}

	// Читаем данные
	products, err := db.Read("products", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read products: %v", err)
		return
	}
	fmt.Printf("   Записей до удаления: %d\n", len(products))

	// Удаляем запись по текстовому фильтру
	deleted, err := db.Delete("name == 'Test Product'", "products", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to delete product: %v", err)
		return
	}
	fmt.Printf("   Удалено записей: %d\n", len(deleted))

	// Проверяем результат
	products, err = db.Read("products", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read products after delete: %v", err)
		return
	}
	fmt.Printf("   Записей после удаления: %d\n", len(products))
}

// testDeleteMultipleRecordsByArray тестирует удаление нескольких записей по массиву данных
func testDeleteMultipleRecordsByArray() {
	// Создаем базу данных
	db := linedb.NewLineDb(nil)

	// Инициализируем базу данных
	initOptions := &linedb.LineDbInitOptions{
		CacheSize: 1000,
		CacheTTL:  10 * time.Second,
		DBFolder:  "./data/test-linedb-delete",
		Collections: []linedb.JSONLFileOptions{
			{
				CollectionName: "orders",
				AllocSize:      256,
				IndexedFields:  []string{"id", "status"},
			},
		},
	}

	if err := db.Init(true, initOptions); err != nil {
		log.Printf("Failed to init database: %v", err)
		return
	}
	defer db.Close()

	// Создаем массив тестовых данных
	orders := []any{
		map[string]any{
			"id":         1,
			"status":     "pending",
			"amount":     100.0,
			"customerId": 1,
		},
		map[string]any{
			"id":         2,
			"status":     "completed",
			"amount":     200.0,
			"customerId": 2,
		},
		map[string]any{
			"id":         3,
			"status":     "pending",
			"amount":     150.0,
			"customerId": 1,
		},
	}

	// Вставляем данные
	if err := db.Insert(orders, "orders", linedb.LineDbAdapterOptions{}); err != nil {
		log.Printf("Failed to insert orders: %v", err)
		return
	}

	// Читаем данные
	ordersData, err := db.Read("orders", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read orders: %v", err)
		return
	}
	fmt.Printf("   Записей до удаления: %d\n", len(ordersData))

	// Удаляем несколько записей по массиву фильтров
	deleteFilters := []any{
		map[string]any{"id": 1},
		map[string]any{"id": 2},
	}
	deleted, err := db.Delete(deleteFilters, "orders", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to delete orders: %v", err)
		return
	}
	fmt.Printf("   Удалено записей: %d\n", len(deleted))

	// Проверяем результат
	ordersData, err = db.Read("orders", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read orders after delete: %v", err)
		return
	}
	fmt.Printf("   Записей после удаления: %d\n", len(ordersData))
}

// testDeleteByPartialMatch тестирует удаление записей по частичному совпадению
func testDeleteByPartialMatch() {
	// Создаем базу данных
	db := linedb.NewLineDb(nil)

	// Инициализируем базу данных
	initOptions := &linedb.LineDbInitOptions{
		CacheSize: 1000,
		CacheTTL:  10 * time.Second,
		DBFolder:  "./data/test-linedb-delete",
		Collections: []linedb.JSONLFileOptions{
			{
				CollectionName: "customers",
				AllocSize:      256,
				IndexedFields:  []string{"id", "name"},
			},
		},
	}

	if err := db.Init(true, initOptions); err != nil {
		log.Printf("Failed to init database: %v", err)
		return
	}
	defer db.Close()

	// Создаем массив тестовых данных
	customers := []any{
		map[string]any{
			"id":    1,
			"name":  "John Doe",
			"email": "john@example.com",
		},
		map[string]any{
			"id":    2,
			"name":  "Jane Smith",
			"email": "jane@example.com",
		},
		map[string]any{
			"id":    3,
			"name":  "John Smith",
			"email": "john.smith@example.com",
		},
	}

	// Вставляем данные
	if err := db.Insert(customers, "customers", linedb.LineDbAdapterOptions{}); err != nil {
		log.Printf("Failed to insert customers: %v", err)
		return
	}

	// Читаем данные
	customersData, err := db.Read("customers", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read customers: %v", err)
		return
	}
	fmt.Printf("   Записей до удаления: %d\n", len(customersData))

	// Удаляем записи по частичному совпадению
	deleted, err := db.Delete(
		map[string]any{"name": "John"},
		"customers",
		linedb.LineDbAdapterOptions{StrictCompare: false},
	)
	if err != nil {
		log.Printf("Failed to delete customers: %v", err)
		return
	}
	fmt.Printf("   Удалено записей с именем 'John': %d\n", len(deleted))

	// Проверяем результат
	customersData, err = db.Read("customers", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read customers after delete: %v", err)
		return
	}
	fmt.Printf("   Записей после удаления: %d\n", len(customersData))
}

// testDeleteFromPartitionedCollections тестирует удаление из партиционированных коллекций
func testDeleteFromPartitionedCollections() {
	// Создаем базу данных
	db := linedb.NewLineDb(nil)

	// Инициализируем базу данных с партициями
	initOptions := &linedb.LineDbInitOptions{
		CacheSize: 1000,
		CacheTTL:  10 * time.Second,
		DBFolder:  "./data/test-linedb-delete",
		Collections: []linedb.JSONLFileOptions{
			{
				CollectionName: "logs",
				AllocSize:      256,
				IndexedFields:  []string{"id", "level"},
			},
		},
		Partitions: []linedb.PartitionCollection{
			{
				CollectionName: "logs",
				PartIDFnStr:    "level",
			},
		},
	}

	if err := db.Init(true, initOptions); err != nil {
		log.Printf("Failed to init database: %v", err)
		return
	}
	defer db.Close()

	// Создаем логи для разных уровней
	logs := []any{
		map[string]any{
			"id":        1,
			"level":     "error",
			"message":   "Critical error occurred",
			"timestamp": time.Now().Unix(),
		},
		map[string]any{
			"id":        2,
			"level":     "info",
			"message":   "User logged in",
			"timestamp": time.Now().Unix(),
		},
		map[string]any{
			"id":        3,
			"level":     "error",
			"message":   "Another error",
			"timestamp": time.Now().Unix(),
		},
	}

	// Вставляем данные
	if err := db.Insert(logs, "logs", linedb.LineDbAdapterOptions{}); err != nil {
		log.Printf("Failed to insert logs: %v", err)
		return
	}

	// Читаем данные
	logsData, err := db.Read("logs", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read logs: %v", err)
		return
	}
	fmt.Printf("   Записей до удаления: %d\n", len(logsData))

	// Удаляем логи с уровнем 'error'
	deleted, err := db.Delete(map[string]any{"level": "error"}, "logs", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to delete error logs: %v", err)
		return
	}
	fmt.Printf("   Удалено записей с уровнем 'error': %d\n", len(deleted))

	// Проверяем результат
	logsData, err = db.Read("logs", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read logs after delete: %v", err)
		return
	}
	fmt.Printf("   Записей после удаления: %d\n", len(logsData))
}

// testDeleteEdgeCases тестирует граничные случаи удаления
func testDeleteEdgeCases() {
	// Создаем базу данных
	db := linedb.NewLineDb(nil)

	// Инициализируем базу данных
	initOptions := &linedb.LineDbInitOptions{
		CacheSize: 1000,
		CacheTTL:  10 * time.Second,
		DBFolder:  "./data/test-linedb-delete",
		Collections: []linedb.JSONLFileOptions{
			{
				CollectionName: "test_data",
				AllocSize:      256,
				IndexedFields:  []string{"id", "type"},
			},
		},
	}

	if err := db.Init(true, initOptions); err != nil {
		log.Printf("Failed to init database: %v", err)
		return
	}
	defer db.Close()

	// Тест удаления несуществующей записи
	fmt.Println("   Тест удаления несуществующей записи:")
	deleted, err := db.Delete(map[string]any{"id": 999}, "test_data", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to delete non-existent record: %v", err)
		return
	}
	fmt.Printf("   Удалено несуществующих записей: %d\n", len(deleted))

	// Тест удаления пустого массива
	fmt.Println("   Тест удаления пустого массива:")
	deleted, err = db.Delete([]any{}, "test_data", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to delete empty array: %v", err)
		return
	}
	fmt.Printf("   Удалено записей из пустого массива: %d\n", len(deleted))

	// Тест удаления записей с разными типами ID
	fmt.Println("   Тест удаления записей с разными типами ID:")

	// Вставляем запись со строковым ID
	stringIDData := map[string]any{
		"id":   "user-1",
		"name": "Test String Id User",
		"type": "string_id",
	}
	if err := db.Insert(stringIDData, "test_data", linedb.LineDbAdapterOptions{}); err != nil {
		log.Printf("Failed to insert string ID data: %v", err)
		return
	}

	// Удаляем запись со строковым ID
	deleted, err = db.Delete("id == 'user-1'", "test_data", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to delete string ID record: %v", err)
		return
	}
	fmt.Printf("   Удалено записей со строковым ID: %d\n", len(deleted))
}

// testDeletePerformance тестирует производительность удаления
func testDeletePerformance() {
	// Создаем базу данных
	db := linedb.NewLineDb(nil)

	// Инициализируем базу данных
	initOptions := &linedb.LineDbInitOptions{
		CacheSize: 10000,
		CacheTTL:  10 * time.Second,
		DBFolder:  "./data/test-linedb-delete",
		Collections: []linedb.JSONLFileOptions{
			{
				CollectionName: "performance_data",
				AllocSize:      1024,
				IndexedFields:  []string{"id", "category"},
			},
		},
	}

	if err := db.Init(true, initOptions); err != nil {
		log.Printf("Failed to init database: %v", err)
		return
	}
	defer db.Close()

	// Создаем большое количество записей
	recordCount := 1000
	fmt.Printf("   Создание %d записей для теста производительности...\n", recordCount)

	largeDataArray := make([]any, recordCount)
	for i := 1; i <= recordCount; i++ {
		largeDataArray[i-1] = map[string]any{
			"id":       i,
			"name":     fmt.Sprintf("User %d", i),
			"category": fmt.Sprintf("Category %d", (i-1)%10+1),
			"value":    float64(i) * 1.5,
		}
	}

	// Вставляем данные
	if err := db.Insert(largeDataArray, "performance_data", linedb.LineDbAdapterOptions{}); err != nil {
		log.Printf("Failed to insert large data array: %v", err)
		return
	}

	// Читаем данные для проверки
	result, err := db.Read("performance_data", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read large data: %v", err)
		return
	}
	fmt.Printf("   Записей в базе: %d\n", len(result))

	// Удаляем половину записей (четные ID)
	startTime := time.Now()
	itemsToDelete := make([]any, recordCount/2)
	for i := 0; i < recordCount/2; i++ {
		itemsToDelete[i] = map[string]any{"id": (i + 1) * 2}
	}

	deleted, err := db.Delete(itemsToDelete, "performance_data", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to delete large number of records: %v", err)
		return
	}
	endTime := time.Now()

	duration := endTime.Sub(startTime)
	fmt.Printf("   Удалено записей: %d\n", len(deleted))
	fmt.Printf("   Время выполнения: %v\n", duration)

	// Проверяем результат
	result, err = db.Read("performance_data", linedb.LineDbAdapterOptions{})
	if err != nil {
		log.Printf("Failed to read data after bulk delete: %v", err)
		return
	}
	fmt.Printf("   Записей после массового удаления: %d\n", len(result))
}

// testDeleteMultipleCollections тестирует удаление из множественных коллекций
func testDeleteMultipleCollections() {
	// Создаем базу данных
	db := linedb.NewLineDb(nil)

	// Инициализируем базу данных с множественными коллекциями
	initOptions := &linedb.LineDbInitOptions{
		CacheSize: 1000,
		CacheTTL:  10 * time.Second,
		DBFolder:  "./data/test-linedb-delete",
		Collections: []linedb.JSONLFileOptions{
			{
				CollectionName: "users",
				AllocSize:      256,
				IndexedFields:  []string{"id", "username"},
			},
			{
				CollectionName: "posts",
				AllocSize:      256,
				IndexedFields:  []string{"id", "authorId"},
			},
			{
				CollectionName: "comments",
				AllocSize:      256,
				IndexedFields:  []string{"id", "postId"},
			},
		},
	}

	if err := db.Init(true, initOptions); err != nil {
		log.Printf("Failed to init database: %v", err)
		return
	}
	defer db.Close()

	// Создаем данные для разных коллекций
	users := []any{
		map[string]any{
			"id":       1,
			"username": "user1",
			"email":    "user1@example.com",
		},
		map[string]any{
			"id":       2,
			"username": "user2",
			"email":    "user2@example.com",
		},
	}

	posts := []any{
		map[string]any{
			"id":       1,
			"title":    "First Post",
			"authorId": 1,
			"content":  "This is the first post",
		},
		map[string]any{
			"id":       2,
			"title":    "Second Post",
			"authorId": 2,
			"content":  "This is the second post",
		},
	}

	comments := []any{
		map[string]any{
			"id":       1,
			"postId":   1,
			"content":  "Great post!",
			"authorId": 2,
		},
		map[string]any{
			"id":       2,
			"postId":   2,
			"content":  "Nice article",
			"authorId": 1,
		},
	}

	// Вставляем данные в разные коллекции
	if err := db.Insert(users, "users", linedb.LineDbAdapterOptions{}); err != nil {
		log.Printf("Failed to insert users: %v", err)
		return
	}

	if err := db.Insert(posts, "posts", linedb.LineDbAdapterOptions{}); err != nil {
		log.Printf("Failed to insert posts: %v", err)
		return
	}

	if err := db.Insert(comments, "comments", linedb.LineDbAdapterOptions{}); err != nil {
		log.Printf("Failed to insert comments: %v", err)
		return
	}

	// Удаляем данные из разных коллекций
	usersDeleted, _ := db.Delete(map[string]any{"id": 1}, "users", linedb.LineDbAdapterOptions{})
	postsDeleted, _ := db.Delete(map[string]any{"authorId": 1}, "posts", linedb.LineDbAdapterOptions{})
	commentsDeleted, _ := db.Delete(map[string]any{"postId": 1}, "comments", linedb.LineDbAdapterOptions{})

	// Читаем данные из всех коллекций
	usersData, _ := db.Read("users", linedb.LineDbAdapterOptions{})
	postsData, _ := db.Read("posts", linedb.LineDbAdapterOptions{})
	commentsData, _ := db.Read("comments", linedb.LineDbAdapterOptions{})

	fmt.Printf("   Удалено пользователей: %d\n", len(usersDeleted))
	fmt.Printf("   Удалено постов: %d\n", len(postsDeleted))
	fmt.Printf("   Удалено комментариев: %d\n", len(commentsDeleted))
	fmt.Printf("   Осталось пользователей: %d\n", len(usersData))
	fmt.Printf("   Осталось постов: %d\n", len(postsData))
	fmt.Printf("   Осталось комментариев: %d\n", len(commentsData))
}
