package packs

import (
	"fmt"

	"github.com/nexuscrm/metadata"
)

func (b *sourceBackedComponentBuildContext) buildRelatedListRule(component ManifestComponent, payload []byte) error {
	packComponent, _, err := newSourceBackedRelatedListRuleComponent(b.p.Name(), component, payload)
	if err != nil {
		return err
	}
	b.p.components = append(b.p.components, packComponent)
	return nil
}

func (b *sourceBackedComponentBuildContext) buildPageLayout(component ManifestComponent, payload []byte) error {
	layout, err := sourceBackedPageLayoutFromPayload(payload, component.BusinessKey, componentPayloadLabel(component))
	if err != nil {
		return err
	}
	if !layout.IsDefault {
		b.pageLayoutBatch.declaredNonDefault = append(b.pageLayoutBatch.declaredNonDefault, sourceBackedPageLayoutBusinessKey{
			ObjectAPIName: layout.ObjectAPIName,
			LayoutName:    layout.LayoutName,
		})
	}
	packComponent, err := newSourceBackedPageLayoutComponent(b.p.Name(), component, payload, b.p.relatedListRules)
	if err != nil {
		return err
	}
	b.p.components = append(b.p.components, packComponent)
	return nil
}

func (b *sourceBackedComponentBuildContext) buildLayoutAssignment(component ManifestComponent, payload []byte) error {
	packComponent, err := newSourceBackedLayoutAssignmentComponent(
		b.p.Name(),
		component,
		payload,
		b.recordTypeIndex,
		b.layoutAssignmentBatch,
	)
	if err != nil {
		return err
	}
	b.p.components = append(b.p.components, packComponent)
	return nil
}

func (b *sourceBackedComponentBuildContext) buildReportType(component ManifestComponent, payload []byte) error {
	payloadLabel := componentPayloadLabel(component)
	packComponent, err := newSourceBackedReportTypeComponent(b.p.Name(), component, payload)
	if err != nil {
		return err
	}
	reportTypes, err := sourceBackedReportTypesFromPayload(payload, payloadLabel)
	if err != nil {
		return err
	}
	for _, reportType := range reportTypes.ReportTypes {
		b.p.appendRuntimeStartupShallowKey(ComponentKindReportType, reportType.FullName)
	}
	b.reportTypeBatch.append(reportTypes)
	b.p.components = append(b.p.components, packComponent)
	return nil
}

func (b *sourceBackedComponentBuildContext) buildUIAction(component ManifestComponent, payload []byte) error {
	payloadLabel := componentPayloadLabel(component)
	packComponent, err := newSourceBackedUIActionComponent(b.p.Name(), component, payload)
	if err != nil {
		return err
	}
	actions, err := parseStandardActionPayload(payload, payloadLabel)
	if err != nil {
		return err
	}
	actionRows, err := expandStandardActionRows(actions, b.p.Name())
	if err != nil {
		return err
	}
	for _, row := range sortedStandardActionRows(actionRows) {
		b.p.appendRuntimeStartupShallowKey(ComponentKindUIAction, JoinComponentBusinessKey(row.ObjectAPIName, row.Name))
	}
	b.p.components = append(b.p.components, packComponent)
	return nil
}

func (b *sourceBackedComponentBuildContext) buildSearchScopeOrder(component ManifestComponent, payload []byte) error {
	packComponent, items, err := newSourceBackedSearchScopeOrderComponent(b.p.Name(), component, payload)
	if err != nil {
		return err
	}
	b.p.searchScopeOrder = append(b.p.searchScopeOrder, items...)
	if err := metadata.ValidatePackSearchScopeOrder(b.p.searchScopeOrder); err != nil {
		return err
	}
	if err := metadata.ValidatePackSearchScopeOrderOwnership(b.p.searchScopeOrder, b.p.ownedObjectAPINames); err != nil {
		return err
	}
	b.p.components = append(b.p.components, packComponent)
	return nil
}

func (b *sourceBackedComponentBuildContext) buildSearchAllDefaultFields(component ManifestComponent, payload []byte) error {
	packComponent, _, err := newSourceBackedSearchAllDefaultFieldsComponent(b.p.Name(), component, payload)
	if err != nil {
		return err
	}
	b.p.components = append(b.p.components, packComponent)
	return nil
}

func (b *sourceBackedComponentBuildContext) buildHrefRewriteFields(component ManifestComponent, payload []byte) error {
	packComponent, fields, err := newSourceBackedHrefRewriteFieldsComponent(b.p.Name(), component, payload)
	if err != nil {
		return err
	}
	if err := validateHrefRewriteFieldsForObjectSpecs(fields, b.packObjectSpecs); err != nil {
		return err
	}
	b.p.hrefRewriteFields = append(b.p.hrefRewriteFields, fields...)
	for _, field := range fields {
		projection, err := hrefRewriteFieldStartupProjection(field)
		if err != nil {
			return fmt.Errorf("href_rewrite_fields %s/%s startup shallow projection: %w", field.ParentApiName, field.FieldApiName, err)
		}
		b.p.appendRuntimeStartupShallowDeclaration(ComponentKindHrefRewriteFields, JoinComponentBusinessKey(field.ParentApiName, field.FieldApiName), projection)
	}
	b.p.components = append(b.p.components, packComponent)
	return nil
}
