package runtimeidentity

import (
	"bytes"
	"context"
	"crypto/subtle"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"os"
	"slices"
	"strings"

	"github.com/nexuscrm/backend/internal/runtimeapi"
	"github.com/pingcap-inc/nexuscrm-api-host/runtimegrpc"
	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/recordsv1"
	"google.golang.org/grpc/metadata"
)

const WorkloadIdentityFileSchemaV1 = "nexuscrm.runtime-workload-identities/v1"

type workloadIdentityFile struct {
	Schema     string                     `json:"schema"`
	Identities []workloadIdentityFileItem `json:"identities"`
}

type workloadIdentityFileItem struct {
	WorkloadID string `json:"workloadId"`
	Token      string `json:"token"`
}

// NewBearerWorkloadAuthority binds one operator-owned credential to one
// workload identity. Authentication owns only credential -> workload; Catalog
// and Runtime security remain the authorization owners.
func NewBearerWorkloadAuthority(workloadID, token string) (runtimegrpc.Authority, runtimeapi.RuntimeBindingSource, error) {
	return NewBearerWorkloadAuthorities(map[string]string{workloadID: token})
}

// LoadBearerWorkloadAuthorities reads the v4 stopped-candidate credential
// document and requires an exact match with the deployment-authorized workload
// set. There is no caller-supplied workload selector or default identity.
func LoadBearerWorkloadAuthorities(
	path string,
	authorizedWorkloadIDs []string,
) (runtimegrpc.Authority, runtimeapi.RuntimeBindingSource, error) {
	raw, err := os.ReadFile(path)
	if err != nil {
		return nil, nil, fmt.Errorf("runtime workload authority: read identities: %w", err)
	}
	decoder := json.NewDecoder(bytes.NewReader(raw))
	decoder.DisallowUnknownFields()
	var document workloadIdentityFile
	if err := decoder.Decode(&document); err != nil {
		return nil, nil, fmt.Errorf("runtime workload authority: decode identities: %w", err)
	}
	if err := decoder.Decode(&struct{}{}); !errors.Is(err, io.EOF) {
		return nil, nil, errors.New(
			"runtime workload authority: identities must contain exactly one JSON document",
		)
	}
	if document.Schema != WorkloadIdentityFileSchemaV1 ||
		len(document.Identities) != len(authorizedWorkloadIDs) {
		return nil, nil, errors.New(
			"runtime workload authority: identity set does not match the deployment selection",
		)
	}
	tokens := make(map[string]string, len(document.Identities))
	for index, identity := range document.Identities {
		if index > 0 &&
			document.Identities[index-1].WorkloadID >= identity.WorkloadID {
			return nil, nil, errors.New(
				"runtime workload authority: identities must be sorted and unique",
			)
		}
		tokens[identity.WorkloadID] = identity.Token
	}
	if !slices.Equal(
		authorizedWorkloadIDs,
		func() []string {
			values := make([]string, 0, len(tokens))
			for workloadID := range tokens {
				values = append(values, workloadID)
			}
			slices.Sort(values)
			return values
		}(),
	) {
		return nil, nil, errors.New(
			"runtime workload authority: identity set does not match the deployment selection",
		)
	}
	return NewBearerWorkloadAuthorities(tokens)
}

// NewBearerWorkloadAuthorities authenticates one of a closed set of distinct
// operator-owned bearer credentials. A token maps to exactly one workload;
// duplicate tokens fail closed because they cannot prove caller identity.
func NewBearerWorkloadAuthorities(
	tokens map[string]string,
) (runtimegrpc.Authority, runtimeapi.RuntimeBindingSource, error) {
	if len(tokens) == 0 {
		return nil, nil, errors.New(
			"runtime workload authority: at least one workload identity is required",
		)
	}
	identityTokens := make(map[string]string, len(tokens))
	byToken := make(map[string]string, len(tokens))
	for workloadID, token := range tokens {
		if strings.TrimSpace(workloadID) != workloadID || workloadID == "" ||
			strings.TrimSpace(token) != token || token == "" {
			return nil, nil, errors.New("runtime workload authority: canonical workload id and token are required")
		}
		if _, duplicate := byToken[token]; duplicate {
			return nil, nil, errors.New(
				"runtime workload authority: bearer credentials must be unique",
			)
		}
		identityTokens[workloadID] = token
		byToken[token] = workloadID
	}
	authority := func(ctx context.Context, _ string) (runtimegrpc.VerifiedCaller, error) {
		values, ok := metadata.FromIncomingContext(ctx)
		if !ok {
			return "", &semantic.Failure{Category: semantic.FailureUnauthenticated}
		}
		authorization := values.Get("authorization")
		if len(authorization) != 1 || !strings.HasPrefix(authorization[0], "Bearer ") {
			return "", &semantic.Failure{Category: semantic.FailureUnauthenticated}
		}
		presented := strings.TrimPrefix(authorization[0], "Bearer ")
		var matched string
		for token, workloadID := range byToken {
			if len(presented) == len(token) &&
				subtle.ConstantTimeCompare([]byte(presented), []byte(token)) == 1 {
				matched = workloadID
			}
		}
		if matched == "" {
			return "", &semantic.Failure{Category: semantic.FailureUnauthenticated}
		}
		return runtimegrpc.VerifiedCaller(matched), nil
	}
	bindings := func(_ context.Context, caller runtimegrpc.VerifiedCaller) (runtimeapi.RuntimeCallerBinding, bool, error) {
		workloadID := string(caller)
		if _, found := identityTokens[workloadID]; !found {
			return runtimeapi.RuntimeCallerBinding{}, false, nil
		}
		return runtimeapi.RuntimeCallerBinding{CallerWorkloadID: workloadID}, true, nil
	}
	return authority, bindings, nil
}
