package metadata

import (
	"context"

	"github.com/nexuscrm/metadata/programchecker"
	"github.com/nexuscrm/shared/pkg/models"
)

type ProgramMetadataReader struct {
	service *MetadataService
}

func NewProgramMetadataReader(service *MetadataService) programchecker.ProgramMetadataReader {
	return ProgramMetadataReader{service: service}
}

func NewProgramValidationRuleReader(service *MetadataService) programchecker.ValidationRuleReader {
	return ProgramMetadataReader{service: service}
}

func (r ProgramMetadataReader) Object(ctx context.Context, apiName string) (*models.ObjectMetadata, bool, error) {
	if r.service == nil {
		return nil, false, programchecker.ErrReaderUnavailable
	}
	schema := r.service.GetSchema(ctx, apiName)
	if schema == nil {
		return nil, false, nil
	}
	return schema, true, nil
}

func (r ProgramMetadataReader) Field(ctx context.Context, objectAPIName, fieldAPIName string) (*models.FieldMetadata, bool, error) {
	if r.service == nil {
		return nil, false, programchecker.ErrReaderUnavailable
	}
	field := r.service.GetField(objectAPIName, fieldAPIName)
	if field == nil {
		return nil, false, nil
	}
	return field, true, nil
}

func (r ProgramMetadataReader) Schemas(ctx context.Context) ([]*models.ObjectMetadata, error) {
	if r.service == nil {
		return nil, programchecker.ErrReaderUnavailable
	}
	schemas := r.service.GetSchemas(ctx)
	out := make([]*models.ObjectMetadata, len(schemas))
	copy(out, schemas)
	return out, nil
}

func (r ProgramMetadataReader) ForeignKeyForRelationship(ctx context.Context, objectAPIName, relationshipName string) (string, bool, error) {
	if r.service == nil {
		return "", false, programchecker.ErrReaderUnavailable
	}
	field, ok := r.service.ForeignKeyForRelationship(ctx, objectAPIName, relationshipName)
	return field, ok, nil
}

func (r ProgramMetadataReader) TargetObjectsForForeignKey(ctx context.Context, objectAPIName, foreignKey string) ([]string, bool, error) {
	if r.service == nil {
		return nil, false, programchecker.ErrReaderUnavailable
	}
	targets, ok := r.service.TargetObjectsForForeignKey(ctx, objectAPIName, foreignKey)
	if !ok {
		return nil, false, nil
	}
	out := append([]string(nil), targets...)
	return out, true, nil
}

func (r ProgramMetadataReader) ValidationRules(ctx context.Context, objectAPIName string) ([]*models.ValidationRule, error) {
	if r.service == nil {
		return nil, programchecker.ErrReaderUnavailable
	}
	return r.service.GetValidationRulesStrict(ctx, objectAPIName)
}
