package app

import (
	"context"
	"fmt"
	"strings"
	"time"

	"github.com/tidbcloud/AgentTeam/internal/core/identifiers"
	"github.com/tidbcloud/AgentTeam/internal/coredb"
)

// CopyAgentRoleBindingForUser copies the current role binding projection from
// one caller-managed agent to another without rematerializing role resources.
func (store *Store) CopyAgentRoleBindingForUser(ctx context.Context, userID string, workspaceID string, sourceAgentID string, targetAgentID string) error {
	sourceAgentID = strings.TrimSpace(sourceAgentID)
	targetAgentID = strings.TrimSpace(targetAgentID)
	if sourceAgentID == "" || targetAgentID == "" {
		return badRequest("sourceAgentId and targetAgentId are required")
	}
	if sourceAgentID == targetAgentID {
		return badRequest("sourceAgentId and targetAgentId must differ")
	}
	if _, err := store.requireAgentOperation(ctx, userID, workspaceID, sourceAgentID); err != nil {
		return err
	}
	if _, err := store.requireAgentOperation(ctx, userID, workspaceID, targetAgentID); err != nil {
		return err
	}

	return coredb.WithTx(ctx, store.db, func(tx coredb.Tx) error {
		row := tx.QueryRow(ctx, `
SELECT binding_kind, role_id, role_version_id, source_preset_role_id,
       source_preset_version_id, active_definition_path, realization_id
FROM agent_role_bindings
WHERE workspace_id = $1 AND agent_id = $2
`, workspaceID, sourceAgentID)

		var bindingKind string
		var roleID string
		var roleVersionID string
		var sourcePresetRoleID string
		var sourcePresetVersionID string
		var activeDefinitionPath string
		var realizationID string
		if err := row.Scan(&bindingKind, &roleID, &roleVersionID, &sourcePresetRoleID, &sourcePresetVersionID, &activeDefinitionPath, &realizationID); err != nil {
			if coredb.IsNotFound(err) || isMissingAgentRoleBindingsTable(err) {
				return nil
			}
			return fmt.Errorf("load source agent role binding: %w", err)
		}

		bindingID, err := identifiers.NewEntityID("arb")
		if err != nil {
			return fmt.Errorf("generate copied agent role binding id: %w", err)
		}
		now := time.Now().UTC()
		_, err = tx.Exec(ctx, `
INSERT INTO agent_role_bindings (
    id, workspace_id, agent_id, binding_kind, role_id, role_version_id,
    source_preset_role_id, source_preset_version_id, active_definition_path,
    realization_id, created_by, updated_by, created_at, updated_at
) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $11, $12, $12)
ON DUPLICATE KEY UPDATE
    binding_kind = VALUES(binding_kind),
    role_id = VALUES(role_id),
    role_version_id = VALUES(role_version_id),
    source_preset_role_id = VALUES(source_preset_role_id),
    source_preset_version_id = VALUES(source_preset_version_id),
    active_definition_path = VALUES(active_definition_path),
    realization_id = VALUES(realization_id),
    updated_by = VALUES(updated_by),
    updated_at = VALUES(updated_at)
`, bindingID, strings.TrimSpace(workspaceID), targetAgentID, strings.TrimSpace(bindingKind), strings.TrimSpace(roleID), strings.TrimSpace(roleVersionID), strings.TrimSpace(sourcePresetRoleID), strings.TrimSpace(sourcePresetVersionID), strings.TrimSpace(activeDefinitionPath), strings.TrimSpace(realizationID), strings.TrimSpace(userID), now)
		if err != nil {
			if isMissingAgentRoleBindingsTable(err) {
				return nil
			}
			return fmt.Errorf("copy agent role binding: %w", err)
		}
		return nil
	})
}
