package app

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

	"github.com/tidbcloud/AgentTeam/internal/coredb"
	"github.com/tidbcloud/AgentTeam/internal/store/model"
)

// Provider connection request snapshots share one provider-neutral contract.
// Only execution details such as Gitea webhook ids or GitHub installation
// verification remain in provider-specific files.
const (
	connectionRequestTargetKey       = "connection_target"
	connectionRequestIDKey           = "connection_id"
	connectionRequestExternalRefKey  = "external_subject_ref"
	connectionRequestDisplayLabelKey = "display_label"
	connectionRequestExistsKey       = "connection_exists"
)

func isProviderConnectionRequestKind(kind string) bool {
	switch strings.TrimSpace(kind) {
	case AppInstallationRequestKindConnect, AppInstallationRequestKindDisconnect:
		return true
	default:
		return false
	}
}

// settleProviderConnectionRequestInTx atomically resolves a provider
// connection request. Both GitHub and Gitea use the same request ledger and
// decision CAS.
func settleProviderConnectionRequestInTx(
	ctx context.Context,
	tx coredb.Tx,
	request AppInstallationRequestView,
	decidedByMemberID string,
	decisionReason string,
	now time.Time,
) error {
	baseConfigJSON, err := model.MarshalJSONObject("resolved service installation request base config", appInstallationRequestStoredBaseConfig(request))
	if err != nil {
		return fmt.Errorf("encode resolved connection request base config: %w", err)
	}
	requestedConfigJSON, err := model.MarshalJSONObject("resolved service installation request config", appInstallationRequestStoredRequestedConfig(request))
	if err != nil {
		return fmt.Errorf("encode resolved connection request config: %w", err)
	}
	result, err := tx.Exec(ctx, `
UPDATE service_installation_requests
SET status = $1,
    decided_by_member_id = $2,
    decision_reason = $3,
    service_installation_id = $4,
    base_config = $5,
    requested_config = $6,
    updated_at = $7,
    decided_at = $7
WHERE id = $8
  AND workspace_id = $9
  AND status = $10
`, AppInstallationRequestStatusApproved, strings.TrimSpace(decidedByMemberID), strings.TrimSpace(decisionReason), strings.TrimSpace(request.InstallationID), baseConfigJSON, requestedConfigJSON, now.UTC(), strings.TrimSpace(request.ID), strings.TrimSpace(request.WorkspaceID), AppInstallationRequestStatusPending)
	if err != nil {
		return fmt.Errorf("approve provider connection request: %w", err)
	}
	if result.RowsAffected() != 1 {
		return conflict("App installation request decision changed.")
	}
	return nil
}
