package app

import (
	"context"
	"fmt"
	"strings"

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

// AccountBehaviorSettingsForUser returns the current user's account-level
// behavior settings.
func (store *Store) AccountBehaviorSettingsForUser(ctx context.Context, userID string) (agent.AccountBehaviorSettings, error) {
	preferences, err := accountPreferencesForUser(ctx, store.db, userID)
	if err != nil {
		return agent.AccountBehaviorSettings{}, err
	}
	return accountBehaviorSettingsFromPreferences(preferences), nil
}

// UpdateAccountBehaviorSettingsForUser updates the current user's account-level
// behavior settings.
func (store *Store) UpdateAccountBehaviorSettingsForUser(ctx context.Context, userID string, update agent.AccountBehaviorSettingsUpdate) (agent.AccountBehaviorSettings, error) {
	trimmedUserID := strings.TrimSpace(userID)
	if trimmedUserID == "" {
		return agent.AccountBehaviorSettings{}, badRequest("userId is required")
	}
	if update.Empty() {
		return agent.AccountBehaviorSettings{}, badRequest("account behavior settings update is empty")
	}
	if update.RuntimeDebugEnabled == nil {
		preferences, err := accountPreferencesForUser(ctx, store.db, trimmedUserID)
		if err != nil {
			return agent.AccountBehaviorSettings{}, err
		}
		return accountBehaviorSettingsFromPreferences(preferences), nil
	}

	preferences, err := store.updateAccountPreferencesForUser(ctx, trimmedUserID, accountPreferencesUpdate{
		RuntimeDebugEnabled: update.RuntimeDebugEnabled,
	})
	if err != nil {
		return agent.AccountBehaviorSettings{}, err
	}
	return accountBehaviorSettingsFromPreferences(preferences), nil
}

func accountBehaviorSettingsFromPreferences(preferences accountPreferences) agent.AccountBehaviorSettings {
	return agent.AccountBehaviorSettings{
		UserID: preferences.UserID,
		// Reply enhancement is now a product default, not an account-level switch.
		VisibleReplyContractEnabled: true,
		RuntimeDebugEnabled:         preferences.RuntimeDebugEnabled,
	}
}

// AgentBehaviorSettingsForUser returns one agent's server-owned behavior
// settings without querying runtime or Machine diagnostic state.
func (store *Store) AgentBehaviorSettingsForUser(ctx context.Context, userID string, workspaceID string, agentID string) (agent.BehaviorSettings, error) {
	trimmedUserID := strings.TrimSpace(userID)
	trimmedWorkspaceID := strings.TrimSpace(workspaceID)
	trimmedAgentID := strings.TrimSpace(agentID)
	return agentBehaviorSettingsForUser(ctx, store.db, trimmedUserID, trimmedWorkspaceID, trimmedAgentID)
}

func agentBehaviorSettingsForUser(ctx context.Context, queryer coredb.QueryRower, userID string, workspaceID string, agentID string) (agent.BehaviorSettings, error) {
	var status string
	var settings agent.BehaviorSettings
	if err := queryer.QueryRow(ctx, `
WITH membership AS (
  SELECT id
  FROM members
  WHERE user_id = $1
    AND workspace_id = $2
    AND type = 'human'
    AND status = 'active'
),
target AS (
  SELECT a.workspace_id,
         a.id,
         TRUE AS account_visible_reply_contract_enabled,
         a.visible_reply_contract_enabled,
         mac.created_by_user_id
  FROM agents a
  JOIN machines mac
    ON mac.workspace_id = a.workspace_id
   AND mac.id = a.machine_id
  WHERE a.workspace_id = $2
    AND a.id = $3
    AND a.status <> 'archived'
    AND mac.status = 'active'
),
authorized AS (
  SELECT target.workspace_id,
         target.id,
         target.account_visible_reply_contract_enabled,
         target.visible_reply_contract_enabled,
         CASE
           WHEN target.created_by_user_id = $1 THEN 1
           ELSE 0
         END AS can_manage
  FROM target
  JOIN membership
)
SELECT 'ok',
       workspace_id,
       id,
       TRUE,
       TRUE,
       TRUE
FROM authorized
WHERE can_manage = 1
UNION ALL
SELECT 'forbidden', COALESCE((SELECT workspace_id FROM target LIMIT 1), ''), COALESCE((SELECT id FROM target LIMIT 1), ''), FALSE, FALSE, FALSE
WHERE NOT EXISTS (SELECT 1 FROM membership)
   OR EXISTS (SELECT 1 FROM authorized WHERE can_manage = 0)
UNION ALL
SELECT 'not_found', '', '', FALSE, FALSE, FALSE
WHERE EXISTS (SELECT 1 FROM membership)
  AND NOT EXISTS (SELECT 1 FROM target)
`, strings.TrimSpace(userID), strings.TrimSpace(workspaceID), strings.TrimSpace(agentID)).Scan(
		&status,
		&settings.WorkspaceID,
		&settings.AgentID,
		&settings.AccountVisibleReplyContract,
		&settings.VisibleReplyContractEnabled,
		&settings.EffectiveVisibleReplyContract,
	); err != nil {
		if coredb.IsNotFound(err) {
			return agent.BehaviorSettings{}, ErrNotFound
		}
		return agent.BehaviorSettings{}, fmt.Errorf("load agent behavior settings: %w", err)
	}
	switch status {
	case "ok":
		return settings, nil
	case "forbidden":
		return agent.BehaviorSettings{}, ErrForbidden
	case "not_found":
		return agent.BehaviorSettings{}, ErrNotFound
	default:
		return agent.BehaviorSettings{}, fmt.Errorf("load agent behavior settings returned unknown status %q", status)
	}
}
