package dialectsfcrm

import (
	"context"
	"strings"

	"github.com/nexuscrm/shared/pkg/constants"
	"github.com/nexuscrm/shared/pkg/models"
)

const runtimeScopedLookupValidator = "runtime_scoped_lookup"

type runtimePicklistFilterMapping struct {
	SourceField string `json:"sourceField"`
	RecordField string `json:"recordField"`
}

type runtimePicklistInfo struct {
	SourceObject   string                         `json:"sourceObject"`
	ValueField     string                         `json:"valueField"`
	LabelField     string                         `json:"labelField"`
	FilterMappings []runtimePicklistFilterMapping `json:"filterMappings"`
	SortField      string                         `json:"sortField,omitempty"`
	SortOrder      string                         `json:"sortOrder,omitempty"`
}

type runtimeLookupFilterMapping struct {
	RecordField string `json:"recordField"`
	SourceField string `json:"sourceField"`
	TargetField string `json:"targetField"`
}

type runtimeLookupInfo struct {
	FilterMappings []runtimeLookupFilterMapping `json:"filterMappings"`
}

type filteredLookupInfo struct {
	RuntimePicklist *runtimePicklistInfo `json:"runtimePicklist,omitempty"`
	RuntimeLookup   *runtimeLookupInfo   `json:"runtimeLookup,omitempty"`
}

type schemaLookup interface {
	getSchema(ctx context.Context, apiName string) *models.ObjectMetadata
}

func buildRuntimePicklistInfo(ctx context.Context, schemas schemaLookup, field models.FieldMetadata) *runtimePicklistInfo {
	if schemas == nil || !models.IsRuntimeScopedPicklist(field) {
		return nil
	}

	normalizedType := constants.NormalizeFieldType(string(field.Type))
	if normalizedType != constants.FieldTypePicklist && normalizedType != constants.FieldTypeMultiPicklist {
		return nil
	}

	if field.ControllingField == nil || len(field.ReferenceTo) != 1 {
		return nil
	}

	recordField := strings.TrimSpace(*field.ControllingField)
	sourceObject := strings.TrimSpace(field.ReferenceTo[0])
	if recordField == "" || sourceObject == "" {
		return nil
	}

	sourceSchema := schemas.getSchema(ctx, sourceObject)
	if sourceSchema == nil {
		return nil
	}

	labelField := runtimePicklistLabelField(sourceSchema)
	if labelField == "" {
		return nil
	}

	sortField, sortOrder := runtimePicklistSort(sourceSchema, labelField)
	return &runtimePicklistInfo{
		SourceObject: sourceSchema.APIName,
		ValueField:   labelField,
		LabelField:   labelField,
		FilterMappings: []runtimePicklistFilterMapping{
			{SourceField: recordField, RecordField: recordField},
		},
		SortField: sortField,
		SortOrder: sortOrder,
	}
}

func buildRuntimeLookupInfo(field models.FieldMetadata) *runtimeLookupInfo {
	if field.Validator == nil {
		return nil
	}
	if !strings.EqualFold(strings.TrimSpace(*field.Validator), runtimeScopedLookupValidator) {
		return nil
	}
	normalizedType := constants.NormalizeFieldType(string(field.Type))
	if normalizedType != constants.FieldTypeReference && normalizedType != constants.FieldTypeMasterDetail {
		return nil
	}

	cfg, err := models.ParseLookupScopeConfig(field.ValidatorConfig)
	if err != nil {
		return nil
	}

	mappings := make([]runtimeLookupFilterMapping, 0, len(cfg.FilterMappings))
	for _, mapping := range cfg.FilterMappings {
		mappings = append(mappings, runtimeLookupFilterMapping{
			RecordField: mapping.RecordField,
			SourceField: mapping.SourceField,
			TargetField: mapping.TargetField,
		})
	}
	return &runtimeLookupInfo{FilterMappings: mappings}
}

func runtimePicklistLabelField(schema *models.ObjectMetadata) string {
	if schema == nil {
		return ""
	}
	for _, field := range schema.Fields {
		if strings.EqualFold(field.APIName, "Label") {
			return field.APIName
		}
	}
	for _, field := range schema.Fields {
		if field.IsNameField {
			return field.APIName
		}
	}
	for _, field := range schema.Fields {
		if strings.EqualFold(field.APIName, "Name") {
			return field.APIName
		}
	}
	return ""
}

func runtimePicklistSort(schema *models.ObjectMetadata, fallback string) (string, string) {
	if schema == nil {
		return fallback, "ASC"
	}
	for _, field := range schema.Fields {
		if strings.EqualFold(field.APIName, "SortOrder") {
			return field.APIName, "ASC"
		}
	}
	return fallback, "ASC"
}
