package app

import (
	"context"
	"fmt"
	"strings"

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

type accountPreferences struct {
	UserID                      string
	VisibleReplyContractEnabled bool
	RuntimeDebugEnabled         bool
}

type accountPreferencesUpdate struct {
	VisibleReplyContractEnabled *bool
	RuntimeDebugEnabled         *bool
}

func (update accountPreferencesUpdate) empty() bool {
	return update.VisibleReplyContractEnabled == nil &&
		update.RuntimeDebugEnabled == nil
}

func accountPreferencesForUser(ctx context.Context, queryer coredb.QueryRower, userID string) (accountPreferences, error) {
	trimmedUserID := strings.TrimSpace(userID)
	if trimmedUserID == "" {
		return accountPreferences{}, badRequest("userId is required")
	}

	var preferences accountPreferences
	if err := queryer.QueryRow(ctx, `
SELECT users.id,
       COALESCE(prefs.visible_reply_contract_enabled, TRUE),
       COALESCE(prefs.runtime_debug_enabled, FALSE)
FROM users
LEFT JOIN user_preferences prefs ON prefs.user_id = users.id
WHERE users.id = $1
`, trimmedUserID).Scan(
		&preferences.UserID,
		&preferences.VisibleReplyContractEnabled,
		&preferences.RuntimeDebugEnabled,
	); err != nil {
		if coredb.IsNotFound(err) {
			return accountPreferences{}, ErrNotFound
		}
		return accountPreferences{}, fmt.Errorf("load account preferences: %w", err)
	}
	return preferences, nil
}

func (store *Store) updateAccountPreferencesForUser(ctx context.Context, userID string, update accountPreferencesUpdate) (accountPreferences, error) {
	trimmedUserID := strings.TrimSpace(userID)
	if trimmedUserID == "" {
		return accountPreferences{}, badRequest("userId is required")
	}
	if update.empty() {
		return accountPreferences{}, badRequest("account preferences update is empty")
	}

	visibleReplyContractEnabled := true
	if update.VisibleReplyContractEnabled != nil {
		visibleReplyContractEnabled = *update.VisibleReplyContractEnabled
	}
	runtimeDebugEnabled := false
	if update.RuntimeDebugEnabled != nil {
		runtimeDebugEnabled = *update.RuntimeDebugEnabled
	}

	assignments := make([]string, 0, 3)
	changeConditions := make([]string, 0, 2)
	if update.VisibleReplyContractEnabled != nil {
		assignments = append(assignments, "visible_reply_contract_enabled = VALUES(visible_reply_contract_enabled)")
		changeConditions = append(changeConditions, "visible_reply_contract_enabled <> VALUES(visible_reply_contract_enabled)")
	}
	if update.RuntimeDebugEnabled != nil {
		assignments = append(assignments, "runtime_debug_enabled = VALUES(runtime_debug_enabled)")
		changeConditions = append(changeConditions, "runtime_debug_enabled <> VALUES(runtime_debug_enabled)")
	}
	assignments = append([]string{`updated_at = CASE
    WHEN ` + strings.Join(changeConditions, `
      OR `) + ` THEN NOW()
    ELSE updated_at
  END`}, assignments...)

	if _, err := store.db.Exec(ctx, `
INSERT INTO user_preferences (
  user_id,
  visible_reply_contract_enabled,
  runtime_debug_enabled,
  created_at,
  updated_at
)
SELECT users.id,
       $2,
       $3,
       NOW(),
       NOW()
FROM users
WHERE users.id = $1
ON DUPLICATE KEY UPDATE
  `+strings.Join(assignments, ",\n  ")+`
`, trimmedUserID, visibleReplyContractEnabled, runtimeDebugEnabled); err != nil {
		return accountPreferences{}, fmt.Errorf("update account preferences: %w", err)
	}
	return accountPreferencesForUser(ctx, store.db, trimmedUserID)
}
