//go:build integration

package metadata

import (
	"context"
	"crypto/rand"
	"encoding/hex"
	"testing"

	"github.com/nexuscrm/backend/pkg/query"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
)

func TestFieldAliasing_BatchCreate_EndToEnd(t *testing.T) {
	conn, ms := SetupIntegrationTest(t)
	// defer conn.Close()

	ctx := context.Background()
	objName := "test_alias_obj_" + generateRandomString(t)

	// 1. Create Object (This creates physical table and default system fields)
	randSuffix := generateRandomString(t)
	objMeta := &models.ObjectMetadata{
		APIName:     objName,
		Label:       "Test Alias Object " + randSuffix,
		PluralLabel: "Test Alias Objects " + randSuffix,
	}
	err := ms.CreateSchema(ctx, objMeta)
	require.NoError(t, err)
	// Defer cleanup
	defer func() {
		_ = ms.DeleteSchema(ctx, objName)
	}()

	// 2. Simulate apply_schema.go: Batch Create Fields including "id"
	// apply_schema sends standard fields like "id" because it only filters "__sys_"
	fields := []models.FieldMetadata{
		{
			APIName:  constants.FieldID,
			Label:    "Record ID - Reclaimed",
			Type:     constants.FieldTypeString,
			IsSystem: false, // Mimic apply_schema sending it as "custom" request
			// Note: PhysicalName is Empty coming from API
		},
		{
			APIName:  "CustomField",
			Label:    "Custom Field",
			Type:     constants.FieldTypeString,
			IsSystem: false,
		},
	}

	// EXECUTE
	_, err = ms.BatchCreateFields(ctx, objName, fields)
	require.NoError(t, err, "BatchCreateFields should not error on 'id' collision (Idempotency)")

	// 3. Verify Metadata in DB
	// Query _System_Field directly to verify physical_name is populated
	db := conn.DB()
	var physicalName string
	q := query.From(constants.TableField).
		SkipID().
		Select([]string{"PhysicalName"}).
		Where("ApiName = ?", constants.FieldID).
		Where("ObjectId = ?", objMeta.ID).
		Build()

	err = db.QueryRow(q.SQL, q.Params...).Scan(&physicalName)
	require.NoError(t, err, "Should find metadata for 'Id'")
	assert.Equal(t, constants.FieldID, physicalName, "Metadata should store Id as PhysicalName for 'Id' field (No Aliasing)")

	// 4. Verify Physical Table Columns
	// Ensure 'Id' DOES exist
	rows, err := db.Query("SELECT * FROM " + objName + " LIMIT 0")
	require.NoError(t, err)
	cols, _ := rows.Columns()
	rows.Close()

	hasID := false
	hasCustom := false
	for _, col := range cols {
		if col == constants.FieldID {
			hasID = true
		}
		if col == "CustomField" {
			hasCustom = true
		}
	}

	assert.True(t, hasID, "Physical table must have 'Id' column")
	assert.True(t, hasCustom, "Physical table must have CustomField")
}

func generateRandomString(t *testing.T) string {
	b := make([]byte, 4)
	_, err := rand.Read(b)
	if err != nil {
		t.Fatal(err)
	}
	return hex.EncodeToString(b)
}
