package permissions

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"strings"

	"github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/permissionauthoringv1"
)

const (
	permissionAuthoringAuditAction  = "Saved permission set authoring"
	permissionAuthoringAuditSection = "Permission Sets"
)

type permissionAuthoringSetupAuditStore interface {
	RecordSetupChange(ctx context.Context, action, section, display, userID string) error
}

// StrictPermissionAuthoringAuditWriter adapts the existing Setup Audit Trail
// repository without the legacy best-effort wrapper. The repository insert
// runs on the caller's transaction context; any failure aborts the aggregate,
// so a committed permission change cannot lack its one aggregate audit row.
type StrictPermissionAuthoringAuditWriter struct {
	store permissionAuthoringSetupAuditStore
}

func NewStrictPermissionAuthoringAuditWriter(store permissionAuthoringSetupAuditStore) (*StrictPermissionAuthoringAuditWriter, error) {
	if store == nil {
		return nil, errors.New("permission authoring audit store is required")
	}
	return &StrictPermissionAuthoringAuditWriter{store: store}, nil
}

func (w *StrictPermissionAuthoringAuditWriter) WritePermissionAuthoringAudit(
	ctx context.Context,
	event PermissionAuthoringAuditEvent,
) error {
	if w == nil || w.store == nil {
		return errors.New("permission authoring audit writer is unavailable")
	}
	if strings.TrimSpace(event.CommandID) == "" || strings.TrimSpace(event.CommandDigest) == "" ||
		strings.TrimSpace(event.ActorID) == "" || !event.SelectedTargetKind.Valid() ||
		strings.TrimSpace(event.SelectedTargetID) == "" || strings.TrimSpace(event.CanonicalPermissionSet) == "" ||
		event.AuthoringRevision == 0 || permissionAuthoringChangeCount(event.FinalChanges) == 0 {
		return errors.New("permission authoring audit event is incomplete")
	}
	payload := struct {
		Schema                 string                        `json:"schema"`
		CommandID              string                        `json:"command_id"`
		CommandDigest          string                        `json:"command_digest"`
		SelectedTargetKind     string                        `json:"selected_target_kind"`
		SelectedTargetID       string                        `json:"selected_target_id"`
		CanonicalPermissionSet string                        `json:"canonical_permission_set"`
		AuthoringRevision      uint64                        `json:"authoring_revision"`
		FinalChanges           permissionauthoringv1.Changes `json:"final_changes"`
	}{
		Schema:                 "nexuscrm.permission-authoring-audit/v1",
		CommandID:              event.CommandID,
		CommandDigest:          event.CommandDigest,
		SelectedTargetKind:     string(event.SelectedTargetKind),
		SelectedTargetID:       event.SelectedTargetID,
		CanonicalPermissionSet: event.CanonicalPermissionSet,
		AuthoringRevision:      event.AuthoringRevision,
		FinalChanges:           clonePermissionAuthoringChanges(event.FinalChanges),
	}
	encoded, err := json.Marshal(payload)
	if err != nil {
		return fmt.Errorf("encode aggregate permission authoring audit: %w", err)
	}
	display := string(encoded)
	if err := w.store.RecordSetupChange(
		ctx,
		permissionAuthoringAuditAction,
		permissionAuthoringAuditSection,
		display,
		event.ActorID,
	); err != nil {
		return fmt.Errorf("record aggregate permission authoring audit: %w", err)
	}
	return nil
}

var _ PermissionAuthoringAuditWriter = (*StrictPermissionAuthoringAuditWriter)(nil)
