package catalogtenant

import (
	"context"
	"database/sql"
	"errors"
	"fmt"

	tenantauthorityv1 "github.com/pingcap-inc/nexuscrm-contract/pkg/tenantlayoutbundleauthorityv1"
)

// ObservedActiveOrgBinding is one current ACTIVE tenant namespace to Catalog
// OrgID binding observed from the tenant authority's durable source rows. It
// is a transient stopped-state preflight fact, not an identity-mapping proof,
// issuer capability, or authorization to map a ProfileKey or RoleKey.
type ObservedActiveOrgBinding struct {
	OrgID             string
	TenantNamespaceID string
}

// InspectActiveOrgBindingLineage opens a source-owned transaction, locks the
// tenant authority fence, and verifies one exact ACTIVE namespace reservation
// and ACTIVE OrgID binding plus their immutable creation commands. It always
// rolls back before returning. A later halted migration must independently
// re-observe and revalidate the source facts in its own mutation transaction.
func (a *Authority) InspectActiveOrgBindingLineage(
	ctx context.Context,
	orgID string,
) (binding ObservedActiveOrgBinding, returnErr error) {
	if a == nil || a.db == nil || a.identity == nil {
		return ObservedActiveOrgBinding{}, ErrConflict
	}
	if err := tenantauthorityv1.ValidateCatalogOrgID(orgID); err != nil {
		return ObservedActiveOrgBinding{}, err
	}

	tx, err := a.db.BeginTx(ctx, nil)
	if err != nil {
		return ObservedActiveOrgBinding{}, err
	}
	defer func() {
		rollbackErr := tx.Rollback()
		if rollbackErr != nil {
			binding = ObservedActiveOrgBinding{}
			returnErr = errors.Join(returnErr, rollbackErr)
		}
	}()

	fenceSequence, err := lockAuthorityFence(ctx, tx)
	if err != nil {
		return ObservedActiveOrgBinding{}, err
	}
	currentBinding, present, err := lockBindingCurrent(ctx, tx, orgID)
	if err != nil {
		return ObservedActiveOrgBinding{}, err
	}
	if !present {
		return ObservedActiveOrgBinding{}, ErrNotFound
	}
	if currentBinding.Value.State != tenantauthorityv1.OrgBindingStateActive {
		return ObservedActiveOrgBinding{}, fmt.Errorf(
			"%w: tenant OrgID binding is not ACTIVE",
			ErrConflict,
		)
	}

	currentNamespace, present, err := lockNamespaceCurrent(
		ctx,
		tx,
		currentBinding.Value.TenantNamespaceID,
	)
	if err != nil {
		return ObservedActiveOrgBinding{}, err
	}
	if !present {
		return ObservedActiveOrgBinding{}, fmt.Errorf(
			"%w: active tenant OrgID binding has no namespace reservation",
			ErrCorrupt,
		)
	}
	if currentNamespace.Value.State != tenantauthorityv1.NamespaceStateActive {
		return ObservedActiveOrgBinding{}, fmt.Errorf(
			"%w: tenant namespace reservation is not ACTIVE",
			ErrConflict,
		)
	}

	namespaceSequence, err := verifyActiveNamespaceReservationCreation(
		ctx,
		tx,
		fenceSequence,
		currentNamespace,
	)
	if err != nil {
		return ObservedActiveOrgBinding{}, err
	}
	bindingSequence, err := verifyActiveOrgBindingCreation(
		ctx,
		tx,
		fenceSequence,
		currentNamespace,
		currentBinding,
	)
	if err != nil {
		return ObservedActiveOrgBinding{}, err
	}
	if namespaceSequence >= bindingSequence {
		return ObservedActiveOrgBinding{}, fmt.Errorf(
			"%w: tenant namespace reserve must precede its OrgID binding",
			ErrCorrupt,
		)
	}

	return ObservedActiveOrgBinding{
		OrgID:             currentBinding.Value.OrgID,
		TenantNamespaceID: currentBinding.Value.TenantNamespaceID,
	}, nil
}

func verifyActiveNamespaceReservationCreation(
	ctx context.Context,
	tx *sql.Tx,
	fenceSequence uint64,
	current namespaceCurrent,
) (uint64, error) {
	rows, err := tx.QueryContext(ctx, `SELECT CommandId, CommandSequence,
TenantNamespaceId, ValueVersion, State, ValueDigest, PriorValueDigest
FROM _System_CatalogTenantNamespaceHistory
WHERE TenantNamespaceId = ? ORDER BY CommandSequence FOR UPDATE`,
		current.Value.TenantNamespaceID,
	)
	if err != nil {
		return 0, err
	}
	defer rows.Close()

	var commandID, rawState string
	var rawSequence, namespaceID []byte
	var value tenantauthorityv1.TenantNamespaceReservationV1
	var digest string
	var prior sql.NullString
	if !rows.Next() {
		if err := rows.Err(); err != nil {
			return 0, err
		}
		return 0, fmt.Errorf("%w: namespace creation history is absent", ErrCorrupt)
	}
	if err := rows.Scan(
		&commandID,
		&rawSequence,
		&namespaceID,
		&value.ValueVersion,
		&rawState,
		&digest,
		&prior,
	); err != nil {
		return 0, err
	}
	if rows.Next() {
		return 0, fmt.Errorf("%w: active namespace has multiple history rows", ErrCorrupt)
	}
	if err := rows.Err(); err != nil {
		return 0, err
	}

	value.TenantNamespaceID = string(namespaceID)
	value.State = tenantauthorityv1.NamespaceState(rawState)
	parsedCommandID := tenantauthorityv1.CommandID(commandID)
	if err := tenantauthorityv1.ValidateCommandID(parsedCommandID); err != nil {
		return 0, fmt.Errorf("%w: namespace history command: %v", ErrCorrupt, err)
	}
	sequence, err := parsePositiveDurableSequence(
		"namespace history CommandSequence",
		rawSequence,
	)
	if err != nil {
		return 0, err
	}
	if sequence > fenceSequence || prior.Valid ||
		value.State != tenantauthorityv1.NamespaceStateActive ||
		value != current.Value || digest != current.Digest ||
		parsedCommandID != current.LastCommandID {
		return 0, fmt.Errorf("%w: namespace creation history differs from current", ErrCorrupt)
	}
	computed, err := tenantauthorityv1.NamespaceValueDigest(value)
	if err != nil || computed != digest {
		return 0, fmt.Errorf("%w: namespace creation value or digest is invalid", ErrCorrupt)
	}

	command, err := readTerminalCommand(ctx, tx, parsedCommandID)
	if err != nil {
		return 0, err
	}
	request := tenantauthorityv1.TenantNamespaceCommandRequest{
		Operation:               tenantauthorityv1.NamespaceOperationReserve,
		TargetTenantNamespaceID: value.TenantNamespaceID,
		DesiredNamespaceValue:   value,
		ExpectedPriorNamespace: tenantauthorityv1.TenantNamespaceExpectedPrior{
			Variant: tenantauthorityv1.NamespaceExpectedPriorAbsent,
		},
	}
	if command.Result != ResultApplied || command.Sequence != sequence ||
		command.Sequence > fenceSequence {
		return 0, fmt.Errorf("%w: namespace creation terminal differs from history", ErrCorrupt)
	}
	if err := validateNamespaceOutcome(request, command); err != nil {
		return 0, fmt.Errorf("%w: namespace creation terminal does not validate: %v", ErrCorrupt, err)
	}
	return sequence, nil
}

func verifyActiveOrgBindingCreation(
	ctx context.Context,
	tx *sql.Tx,
	fenceSequence uint64,
	namespace namespaceCurrent,
	current bindingCurrent,
) (uint64, error) {
	rows, err := tx.QueryContext(ctx, `SELECT CommandId, CommandSequence,
OrgId, TenantNamespaceId, ValueVersion, State, ValueDigest, PriorValueDigest
FROM _System_CatalogTenantOrgNamespaceBindingHistory
WHERE OrgId = ? ORDER BY CommandSequence FOR UPDATE`,
		current.Value.OrgID,
	)
	if err != nil {
		return 0, err
	}
	defer rows.Close()

	var commandID, rawState string
	var rawSequence, orgID, namespaceID []byte
	var value tenantauthorityv1.TenantOrgNamespaceBindingV1
	var digest string
	var prior sql.NullString
	if !rows.Next() {
		if err := rows.Err(); err != nil {
			return 0, err
		}
		return 0, fmt.Errorf("%w: OrgID binding creation history is absent", ErrCorrupt)
	}
	if err := rows.Scan(
		&commandID,
		&rawSequence,
		&orgID,
		&namespaceID,
		&value.ValueVersion,
		&rawState,
		&digest,
		&prior,
	); err != nil {
		return 0, err
	}
	if rows.Next() {
		return 0, fmt.Errorf("%w: active OrgID binding has multiple history rows", ErrCorrupt)
	}
	if err := rows.Err(); err != nil {
		return 0, err
	}

	value.OrgID = string(orgID)
	value.TenantNamespaceID = string(namespaceID)
	value.State = tenantauthorityv1.OrgBindingState(rawState)
	parsedCommandID := tenantauthorityv1.CommandID(commandID)
	if err := tenantauthorityv1.ValidateCommandID(parsedCommandID); err != nil {
		return 0, fmt.Errorf("%w: OrgID binding history command: %v", ErrCorrupt, err)
	}
	sequence, err := parsePositiveDurableSequence(
		"OrgID binding history CommandSequence",
		rawSequence,
	)
	if err != nil {
		return 0, err
	}
	if sequence > fenceSequence || prior.Valid ||
		value.State != tenantauthorityv1.OrgBindingStateActive ||
		value != current.Value || digest != current.Digest ||
		parsedCommandID != current.LastCommandID {
		return 0, fmt.Errorf("%w: OrgID binding creation history differs from current", ErrCorrupt)
	}
	computed, err := tenantauthorityv1.OrgBindingValueDigest(value)
	if err != nil || computed != digest {
		return 0, fmt.Errorf("%w: OrgID binding creation value or digest is invalid", ErrCorrupt)
	}

	command, err := readTerminalCommand(ctx, tx, parsedCommandID)
	if err != nil {
		return 0, err
	}
	request := tenantauthorityv1.TenantOrgNamespaceBindingCommandRequest{
		Operation:                          tenantauthorityv1.BindingOperationBind,
		TargetOrgID:                        value.OrgID,
		DesiredBindingValue:                value,
		ExpectedNamespaceReservationDigest: namespace.Digest,
		ExpectedPriorBinding: tenantauthorityv1.TenantOrgBindingExpectedPrior{
			Variant: tenantauthorityv1.BindingExpectedPriorAbsent,
		},
	}
	if command.Result != ResultApplied || command.Sequence != sequence ||
		command.Sequence > fenceSequence {
		return 0, fmt.Errorf("%w: OrgID binding creation terminal differs from history", ErrCorrupt)
	}
	if err := validateBindingOutcome(request, command); err != nil {
		return 0, fmt.Errorf("%w: OrgID binding creation terminal does not validate: %v", ErrCorrupt, err)
	}
	return sequence, nil
}
