package metadata

import (
	"context"
	"regexp"
	"testing"

	"github.com/nexuscrm/kernel/pkg/ports"
	domainSchema "github.com/nexuscrm/kernel/pkg/schema"
	"github.com/nexuscrm/persistence"
	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
)

func TestPhysicalNameAndMetadataFlowIdentifierOwnersStayExplicit(t *testing.T) {
	const (
		objectAPIName = "EnvelopeProbe__c"
		fieldAPIName  = "LogicalValue__c"
		keyPrefix     = "a09"
	)
	prefix := keyPrefix
	repo := &identifierOwnerMetadataRepo{schema: &models.ObjectMetadata{APIName: objectAPIName, KeyPrefix: &prefix}}
	service := NewMetadataService(repo, NewSchemaManager(persistence.NewSchemaRepository(nil, nil)), nil)
	schema := &models.ObjectMetadata{
		APIName: objectAPIName,
		Label:   "Envelope Probe",
		Fields: []models.FieldMetadata{{
			APIName: fieldAPIName,
			Label:   "Logical Value",
			Type:    constants.FieldTypeString,
		}},
	}

	definition, _, err := service.PrepareTableDefinition(context.Background(), schema)
	if err != nil {
		t.Fatalf("PrepareTableDefinition: %v", err)
	}
	if definition.TableName != objectAPIName {
		t.Fatalf("physical table = %q, want current API-name owner %q", definition.TableName, objectAPIName)
	}

	idColumn := metadataIdentifierOwnerColumn(t, definition.Columns, constants.FieldID)
	if idColumn.Type != "VARCHAR(36)" || !idColumn.PrimaryKey {
		t.Fatalf("generic Id column = {type:%q primary:%v}, want VARCHAR(36) primary key", idColumn.Type, idColumn.PrimaryKey)
	}
	fieldColumn := metadataIdentifierOwnerColumn(t, definition.Columns, fieldAPIName)
	if fieldColumn.Name != fieldAPIName {
		t.Fatalf("physical field column = %q, want current API-name owner %q", fieldColumn.Name, fieldAPIName)
	}
	for _, field := range schema.Fields {
		if field.APIName == fieldAPIName && field.PhysicalName != fieldAPIName {
			t.Fatalf("field PhysicalName = %q, want current API-name owner %q", field.PhysicalName, fieldAPIName)
		}
	}

	metadataFlowID := service.generateStandardSObjectID(context.Background(), objectAPIName)
	if !regexp.MustCompile(`^` + keyPrefix + `[0-9]{15}$`).MatchString(metadataFlowID) {
		t.Fatalf("generated metadata-flow ID = %q, want 3-byte prefix plus 15 digits", metadataFlowID)
	}
}

type identifierOwnerMetadataRepo struct {
	ports.MetadataRepository
	schema *models.ObjectMetadata
}

func (r *identifierOwnerMetadataRepo) GetAllSchemas(context.Context) ([]*models.ObjectMetadata, error) {
	return []*models.ObjectMetadata{r.schema}, nil
}

func (r *identifierOwnerMetadataRepo) GetAllRelationships(context.Context) ([]*models.Relationship, error) {
	return nil, nil
}

func metadataIdentifierOwnerColumn(t *testing.T, columns []domainSchema.ColumnDefinition, name string) domainSchema.ColumnDefinition {
	t.Helper()
	for _, column := range columns {
		if column.Name == name {
			return column
		}
	}
	t.Fatalf("column %q not found", name)
	return domainSchema.ColumnDefinition{}
}
