import { defineStore } from 'pinia';
import { useModelStore } from './model';
import { persistDefaultHideWorkspace, useUiStore } from './ui';

export type BlockDisplayMode = 'traditional' | 'stacked' | 'minimal';
export type CompactMessageDisplay = 'full' | 'brief';
type RunMode = 'fast' | 'thinking' | 'deep';
type PermissionMode = 'readonly' | 'approval' | 'auto_approval' | 'unrestricted';
type CommunicationStyle = 'default' | 'human_like' | 'auto';
type ConversationContinuity = 'low' | 'medium' | 'high';
type VersioningBackupMode = 'shallow' | 'full';

interface PersonalForm {
  enabled: boolean;
  communication_style: CommunicationStyle;
  conversation_continuity: ConversationContinuity;
  auto_generate_title: boolean;
  recent_conversations_prompt_enabled: boolean;
  recent_conversations_prompt_limit: number | string;
  tool_intent_enabled: boolean;
  skill_hints_enabled: boolean;
  skill_strict_terminal_enabled: boolean;
  skill_strict_sub_agent_enabled: boolean;
  skill_strict_run_command_foreground_enabled: boolean;
  skill_strict_run_command_background_enabled: boolean;
  silent_tool_disable: boolean;
  enhanced_tool_display: boolean;
  compact_message_display: CompactMessageDisplay;
  block_display_mode: BlockDisplayMode;
  show_status_avatar: boolean;
  show_git_status_bar: boolean;
  auto_open_terminal_panel: boolean;
  stacked_hide_borders: boolean;
  minimal_expand_height_limited: boolean;
  enhanced_tool_display_categories: string[];
  enabled_skills: string[];
  self_identify: string;
  user_name: string;
  use_custom_names: boolean;
  profession: string;
  tone: string;
  considerations: string;
  thinking_interval: number | null;
  disabled_tool_categories: string[];
  default_run_mode: RunMode | null;
  default_permission_mode: PermissionMode;
  versioning_enabled_by_default: boolean;
  versioning_backup_mode: VersioningBackupMode;
  versioning_restore_mode: 'overwrite';
  default_model: string | null;
  image_compression: string;
  auto_shallow_compress_enabled: boolean;
  auto_deep_compress_enabled: boolean;
  shallow_compress_trigger_tokens: number | null;
  shallow_compress_keep_recent_tools: number | null;
  shallow_compress_keep_user_turn_tools: number | null;
  shallow_compress_max_replace_per_round: number | null;
  shallow_compress_trigger_tool_calls_interval: number | null;
  deep_compress_trigger_tokens: number | null;
  deep_compress_form: 'file' | 'inject';
  agents_md_auto_inject: boolean;
  allow_root_file_creation: boolean;
  default_hide_workspace: boolean;
  group_sidebar_by_workspace: boolean;
  sidebar_pinned_workspaces: string[];
  sidebar_workspace_order: string[];
  theme: 'classic' | 'light' | 'dark';
  goal_review_mode: 'readonly' | 'active';
  goal_end_conditions: string[];
  goal_max_turns: number;
  goal_max_tokens: number | null;
}

interface ExperimentState {
  blockDisplayMode: BlockDisplayMode;
  compactMessageDisplay: CompactMessageDisplay;
}

interface PersonalizationState {
  visible: boolean;
  loading: boolean;
  saving: boolean;
  loaded: boolean;
  status: string;
  error: string;
  toggleUpdating: boolean;
  overlayPressActive: boolean;
  tonePresets: string[];
  form: PersonalForm;
  toolCategories: Array<{ id: string; label: string }>;
  skillsCatalog: Array<{ id: string; label: string; description?: string }>;
  thinkingIntervalDefault: number;
  thinkingIntervalRange: { min: number; max: number };
  recentConversationsPromptLimitRange: { min: number; max: number };
  experiments: ExperimentState;
}

const DEFAULT_INTERVAL = 10;
const DEFAULT_INTERVAL_RANGE = { min: 1, max: 50 };
const DEFAULT_RECENT_CONVERSATIONS_PROMPT_LIMIT = 10;
const DEFAULT_RECENT_CONVERSATIONS_PROMPT_LIMIT_RANGE = { min: 1, max: 30 };
const DEFAULT_SHALLOW_COMPRESS_TRIGGER_TOKENS = 80000;
const DEFAULT_DEEP_COMPRESS_TRIGGER_TOKENS = 150000;
const RUN_MODE_OPTIONS: RunMode[] = ['fast', 'thinking', 'deep'];
const EXPERIMENT_STORAGE_KEY = 'agents_personalization_experiments';
const THEME_STORAGE_KEY = 'agents_ui_theme';
const STACKED_HIDE_BORDERS_STORAGE_KEY = 'agents_stacked_hide_borders';
const MINIMAL_EXPAND_HEIGHT_LIMITED_STORAGE_KEY = 'agents_minimal_expand_height_limited';

const loadCachedTheme = (): PersonalForm['theme'] => {
  if (typeof window === 'undefined' || !window.localStorage) {
    return 'classic';
  }
  const saved = window.localStorage.getItem(THEME_STORAGE_KEY);
  return saved === 'light' || saved === 'dark' || saved === 'classic' ? saved : 'classic';
};

const loadCachedStackedHideBorders = (): boolean => {
  if (typeof window === 'undefined' || !window.localStorage) {
    return false;
  }
  return window.localStorage.getItem(STACKED_HIDE_BORDERS_STORAGE_KEY) === 'true';
};

const loadCachedBlockDisplayMode = (): BlockDisplayMode => {
  if (typeof window === 'undefined' || !window.localStorage) {
    return 'stacked';
  }
  try {
    const raw = window.localStorage.getItem(EXPERIMENT_STORAGE_KEY);
    if (!raw) {
      return 'stacked';
    }
    const parsed = JSON.parse(raw);
    if (
      typeof parsed?.blockDisplayMode === 'string' &&
      ['traditional', 'stacked', 'minimal'].includes(parsed.blockDisplayMode)
    ) {
      return parsed.blockDisplayMode as BlockDisplayMode;
    }
  } catch (error) {
    console.warn('读取堆叠块显示模式缓存失败：', error);
  }
  return 'stacked';
};

const persistStackedHideBorders = (value: boolean) => {
  if (typeof window === 'undefined' || !window.localStorage) {
    return;
  }
  try {
    window.localStorage.setItem(STACKED_HIDE_BORDERS_STORAGE_KEY, value ? 'true' : 'false');
  } catch (error) {
    console.warn('写入堆叠块边线设置失败：', error);
  }
};

const loadCachedMinimalExpandHeightLimited = (): boolean => {
  if (typeof window === 'undefined' || !window.localStorage) {
    return true;
  }
  const saved = window.localStorage.getItem(MINIMAL_EXPAND_HEIGHT_LIMITED_STORAGE_KEY);
  return saved === null ? true : saved === 'true';
};

const persistMinimalExpandHeightLimited = (value: boolean) => {
  if (typeof window === 'undefined' || !window.localStorage) {
    return;
  }
  try {
    window.localStorage.setItem(MINIMAL_EXPAND_HEIGHT_LIMITED_STORAGE_KEY, value ? 'true' : 'false');
  } catch (error) {
    console.warn('写入极简展开高度限制设置失败：', error);
  }
};

const defaultForm = (): PersonalForm => ({
  enabled: false,
  communication_style: 'default',
  conversation_continuity: 'medium',
  auto_generate_title: true,
  recent_conversations_prompt_enabled: false,
  recent_conversations_prompt_limit: DEFAULT_RECENT_CONVERSATIONS_PROMPT_LIMIT,
  tool_intent_enabled: true,
  skill_hints_enabled: false,
  skill_strict_terminal_enabled: false,
  skill_strict_sub_agent_enabled: false,
  skill_strict_run_command_foreground_enabled: false,
  skill_strict_run_command_background_enabled: false,
  silent_tool_disable: false,
  enhanced_tool_display: true,
  compact_message_display: 'full',
  block_display_mode: loadCachedBlockDisplayMode(),
  show_status_avatar: true,
  show_git_status_bar: true,
  auto_open_terminal_panel: true,
  stacked_hide_borders: loadCachedStackedHideBorders(),
  minimal_expand_height_limited: loadCachedMinimalExpandHeightLimited(),
  enhanced_tool_display_categories: [],
  enabled_skills: [],
  self_identify: '',
  user_name: '',
  use_custom_names: false,
  profession: '',
  tone: '',
  considerations: '',
  thinking_interval: null,
  disabled_tool_categories: [],
  default_run_mode: null,
  default_permission_mode: 'unrestricted',
  versioning_enabled_by_default: true,
  versioning_backup_mode: 'shallow',
  versioning_restore_mode: 'overwrite',
  default_model: null,
  image_compression: 'original',
  auto_shallow_compress_enabled: false,
  auto_deep_compress_enabled: false,
  shallow_compress_trigger_tokens: null,
  shallow_compress_keep_recent_tools: null,
  shallow_compress_keep_user_turn_tools: null,
  shallow_compress_max_replace_per_round: null,
  shallow_compress_trigger_tool_calls_interval: null,
  deep_compress_trigger_tokens: null,
  deep_compress_form: 'file',
  agents_md_auto_inject: false,
  allow_root_file_creation: false,
  default_hide_workspace: false,
  group_sidebar_by_workspace: false,
  sidebar_pinned_workspaces: [],
  sidebar_workspace_order: [],
  theme: loadCachedTheme(),
  goal_review_mode: 'readonly',
  goal_end_conditions: ['max_turns'],
  goal_max_turns: 5,
  goal_max_tokens: null
});

const defaultExperimentState = (): ExperimentState => ({
  blockDisplayMode: 'stacked',
  compactMessageDisplay: 'full'
});

const loadExperimentState = (): ExperimentState => {
  if (typeof window === 'undefined' || !window.localStorage) {
    return defaultExperimentState();
  }
  try {
    const raw = window.localStorage.getItem(EXPERIMENT_STORAGE_KEY);
    if (!raw) {
      return defaultExperimentState();
    }
    const parsed = JSON.parse(raw);

    // 兼容旧版 stackedBlocksEnabled
    let blockDisplayMode: BlockDisplayMode = defaultExperimentState().blockDisplayMode;
    if (
      typeof parsed?.blockDisplayMode === 'string' &&
      ['traditional', 'stacked', 'minimal'].includes(parsed.blockDisplayMode)
    ) {
      blockDisplayMode = parsed.blockDisplayMode;
    } else if (typeof parsed?.stackedBlocksEnabled === 'boolean') {
      // 兼容旧版：true -> stacked, false -> traditional
      blockDisplayMode = parsed.stackedBlocksEnabled ? 'stacked' : 'traditional';
    }

    let compactMessageDisplay: CompactMessageDisplay =
      defaultExperimentState().compactMessageDisplay;
    if (
      typeof parsed?.compactMessageDisplay === 'string' &&
      ['full', 'brief'].includes(parsed.compactMessageDisplay)
    ) {
      compactMessageDisplay = parsed.compactMessageDisplay;
    }

    return {
      blockDisplayMode,
      compactMessageDisplay
    };
  } catch (error) {
    console.warn('无法读取实验功能设置：', error);
    return defaultExperimentState();
  }
};

// 防抖自动保存计时器（非响应式，避免触发不必要的重渲染）
let autoSaveTimer: ReturnType<typeof setTimeout> | null = null;

export const usePersonalizationStore = defineStore('personalization', {
  state: (): PersonalizationState => ({
    visible: false,
    loading: false,
    saving: false,
    loaded: false,
    status: '',
    error: '',
    toggleUpdating: false,
    overlayPressActive: false,
    tonePresets: ['健谈', '幽默', '直言不讳', '鼓励性', '诗意', '企业商务', '打破常规', '同理心'],
    form: defaultForm(),
    toolCategories: [],
    skillsCatalog: [],
    thinkingIntervalDefault: DEFAULT_INTERVAL,
    thinkingIntervalRange: { ...DEFAULT_INTERVAL_RANGE },
    recentConversationsPromptLimitRange: { ...DEFAULT_RECENT_CONVERSATIONS_PROMPT_LIMIT_RANGE },
    experiments: loadExperimentState()
  }),
  actions: {
    async openDrawer() {
      this.visible = true;
      // 每次打开都刷新数据，确保显示最新内容
      if (!this.loading) {
        await this.fetchPersonalization();
      }
    },
    closeDrawer() {
      this.visible = false;
      this.overlayPressActive = false;
    },
    handleOverlayPressStart(event: Event) {
      if (event && (event as MouseEvent).type === 'mousedown') {
        const mouse = event as MouseEvent;
        if (mouse.button !== 0) {
          return;
        }
      }
      this.overlayPressActive = true;
    },
    handleOverlayPressEnd() {
      if (!this.overlayPressActive) {
        return;
      }
      this.overlayPressActive = false;
      this.closeDrawer();
    },
    handleOverlayPressCancel() {
      this.overlayPressActive = false;
    },
    async fetchPersonalization() {
      this.loading = true;
      this.error = '';
      try {
        const resp = await fetch('/api/personalization');
        const result = await resp.json();
        if (!resp.ok || !result.success) {
          throw new Error(result.error || '加载失败');
        }
        this.applyPersonalizationData(result.data || {});
        this.applyPersonalizationMeta(result);
        this.loaded = true;
      } catch (error: any) {
        this.error = error?.message || '加载失败';
      } finally {
        this.loading = false;
      }
    },
    applyPersonalizationData(data: any) {
      // 若后端未返回默认模型（旧版本接口），保持当前已选模型而不是回退到内置模型
      const fallbackModel =
        this.form && typeof this.form.default_model === 'string' ? this.form.default_model : null;
      const fallbackTheme = this.form?.theme || loadCachedTheme();
      this.form = {
        enabled: !!data.enabled,
        communication_style:
          data.communication_style === 'human_like' || data.communication_style === 'auto'
            ? data.communication_style
            : 'default',
        conversation_continuity:
          data.conversation_continuity === 'low' || data.conversation_continuity === 'high'
            ? data.conversation_continuity
            : 'medium',
        auto_generate_title: data.auto_generate_title !== false,
        recent_conversations_prompt_enabled: !!data.recent_conversations_prompt_enabled,
        recent_conversations_prompt_limit: this.normalizeRecentConversationsPromptLimit(
          data.recent_conversations_prompt_limit
        ),
        tool_intent_enabled: !!data.tool_intent_enabled,
        skill_hints_enabled: !!data.skill_hints_enabled,
        skill_strict_terminal_enabled: !!data.skill_strict_terminal_enabled,
        skill_strict_sub_agent_enabled: !!data.skill_strict_sub_agent_enabled,
        skill_strict_run_command_foreground_enabled:
          !!data.skill_strict_run_command_foreground_enabled,
        skill_strict_run_command_background_enabled:
          !!data.skill_strict_run_command_background_enabled,
        silent_tool_disable: !!data.silent_tool_disable,
        enhanced_tool_display: data.enhanced_tool_display !== false,
        compact_message_display: data.compact_message_display === 'brief' ? 'brief' : 'full',
        block_display_mode:
          data.block_display_mode === 'traditional' ||
          data.block_display_mode === 'stacked' ||
          data.block_display_mode === 'minimal'
            ? data.block_display_mode
            : 'stacked',
        show_status_avatar: data.show_status_avatar !== false,
        show_git_status_bar: data.show_git_status_bar !== false,
        auto_open_terminal_panel: data.auto_open_terminal_panel !== false,
        stacked_hide_borders: !!data.stacked_hide_borders,
        minimal_expand_height_limited: data.minimal_expand_height_limited !== false,
        enhanced_tool_display_categories: Array.isArray(data.enhanced_tool_display_categories)
          ? data.enhanced_tool_display_categories.filter(
              (item: unknown) => typeof item === 'string'
            )
          : [],
        enabled_skills: Array.isArray(data.enabled_skills)
          ? data.enabled_skills.filter((item: unknown) => typeof item === 'string')
          : [],
        self_identify: data.self_identify || '',
        user_name: data.user_name || '',
        use_custom_names: !!data.use_custom_names,
        profession: data.profession || '',
        tone: data.tone || '',
        considerations:
          typeof data.considerations === 'string'
            ? data.considerations
            : Array.isArray(data.considerations)
              ? data.considerations.filter((item: unknown) => typeof item === 'string').join('\n')
              : '',
        thinking_interval:
          typeof data.thinking_interval === 'number' ? data.thinking_interval : null,
        disabled_tool_categories: Array.isArray(data.disabled_tool_categories)
          ? data.disabled_tool_categories.filter((item: unknown) => typeof item === 'string')
          : [],
        default_run_mode:
          typeof data.default_run_mode === 'string' &&
          RUN_MODE_OPTIONS.includes(data.default_run_mode as RunMode)
            ? (data.default_run_mode as RunMode)
            : null,
        default_permission_mode:
          data.default_permission_mode === 'readonly' ||
          data.default_permission_mode === 'approval' ||
          data.default_permission_mode === 'auto_approval' ||
          data.default_permission_mode === 'unrestricted'
            ? data.default_permission_mode
            : 'unrestricted',
        versioning_enabled_by_default: data.versioning_enabled_by_default !== false,
        versioning_backup_mode: data.versioning_backup_mode === 'full' ? 'full' : 'shallow',
        versioning_restore_mode: 'overwrite',
        default_model: typeof data.default_model === 'string' ? data.default_model : fallbackModel,
        image_compression:
          typeof data.image_compression === 'string' ? data.image_compression : 'original',
        auto_shallow_compress_enabled: !!data.auto_shallow_compress_enabled,
        auto_deep_compress_enabled: !!data.auto_deep_compress_enabled,
        shallow_compress_trigger_tokens: this.normalizeCompressionNumber(
          data.shallow_compress_trigger_tokens
        ),
        shallow_compress_keep_recent_tools: this.normalizeCompressionNumber(
          data.shallow_compress_keep_recent_tools
        ),
        shallow_compress_keep_user_turn_tools: this.normalizeCompressionNumber(
          data.shallow_compress_keep_user_turn_tools
        ),
        shallow_compress_max_replace_per_round: this.normalizeCompressionNumber(
          data.shallow_compress_max_replace_per_round
        ),
        shallow_compress_trigger_tool_calls_interval: this.normalizeCompressionNumber(
          data.shallow_compress_trigger_tool_calls_interval
        ),
        deep_compress_trigger_tokens: this.normalizeCompressionNumber(
          data.deep_compress_trigger_tokens
        ),
        deep_compress_form: data.deep_compress_form === 'inject' ? 'inject' : 'file',
        agents_md_auto_inject: !!data.agents_md_auto_inject,
        allow_root_file_creation: !!data.allow_root_file_creation,
        default_hide_workspace: !!data.default_hide_workspace,
        group_sidebar_by_workspace: !!data.group_sidebar_by_workspace,
        sidebar_pinned_workspaces: Array.isArray(data.sidebar_pinned_workspaces)
          ? data.sidebar_pinned_workspaces.filter((item: unknown) => typeof item === 'string')
          : [],
        sidebar_workspace_order: Array.isArray(data.sidebar_workspace_order)
          ? data.sidebar_workspace_order.filter((item: unknown) => typeof item === 'string')
          : [],
        theme: ['classic', 'light', 'dark'].includes(data.theme) ? data.theme : fallbackTheme,
        goal_review_mode: data.goal_review_mode === 'active' ? 'active' : 'readonly',
        goal_end_conditions: Array.isArray(data.goal_end_conditions)
          ? data.goal_end_conditions.filter((x: any) => x === 'max_turns' || x === 'max_tokens')
          : ['max_turns'],
        goal_max_turns:
          typeof data.goal_max_turns === 'number' && data.goal_max_turns > 0
            ? data.goal_max_turns
            : 5,
        goal_max_tokens:
          typeof data.goal_max_tokens === 'number' && data.goal_max_tokens > 0
            ? data.goal_max_tokens
            : null
      };
      // 如果theme发生变化，应用到界面
      const currentTheme =
        typeof window !== 'undefined' && window.localStorage
          ? window.localStorage.getItem(THEME_STORAGE_KEY)
          : null;
      if (this.form.theme !== currentTheme) {
        this.applyTheme(this.form.theme);
      }
      persistDefaultHideWorkspace(this.form.default_hide_workspace);
      persistStackedHideBorders(this.form.stacked_hide_borders);
      persistMinimalExpandHeightLimited(this.form.minimal_expand_height_limited);
      if (this.form.default_hide_workspace) {
        useUiStore().setWorkspaceCollapsed(true);
      }
      // 简略消息显示：以配置文件为准，同步到旧版 localStorage 镜像供 ChatArea 读取。
      // 一次性迁移：后端仍为默认 full，但本地缓存遗留 brief（旧版纯前端记录）时，回写到配置文件。
      const cachedCompact = this.experiments.compactMessageDisplay;
      if (this.form.compact_message_display === 'full' && cachedCompact === 'brief') {
        this.form = { ...this.form, compact_message_display: 'brief' };
        void this.persistCompactMessageDisplay('brief');
      }
      // 一次性迁移：堆叠块显示模式旧版仅在 localStorage 保存，后端默认 stacked 时回写本地缓存值。
      const cachedBlockMode = this.experiments.blockDisplayMode;
      if (this.form.block_display_mode === 'stacked' && cachedBlockMode !== 'stacked') {
        this.form = { ...this.form, block_display_mode: cachedBlockMode };
      }
      this.experiments = {
        ...this.experiments,
        compactMessageDisplay: this.form.compact_message_display,
        blockDisplayMode: this.form.block_display_mode
      };
      this.persistExperiments();
      this.clearFeedback();
    },
    applyTheme(theme: 'classic' | 'light' | 'dark') {
      if (typeof window === 'undefined') return;
      // 同步到localStorage
      window.localStorage.setItem(THEME_STORAGE_KEY, theme);
      // 应用主题
      const root = document.documentElement;
      root.setAttribute('data-theme', theme);
      document.body.setAttribute('data-theme', theme);
    },
    normalizeCompressionNumber(value: any): number | null {
      if (value === null || typeof value === 'undefined' || value === '') {
        return null;
      }
      const parsed = Number(value);
      if (!Number.isFinite(parsed)) {
        return null;
      }
      const rounded = Math.round(parsed);
      if (rounded <= 0) {
        return null;
      }
      return rounded;
    },
    normalizeRecentConversationsPromptLimit(value: any): number {
      const parsed = Number(value);
      const min =
        this.recentConversationsPromptLimitRange.min ??
        DEFAULT_RECENT_CONVERSATIONS_PROMPT_LIMIT_RANGE.min;
      const max =
        this.recentConversationsPromptLimitRange.max ??
        DEFAULT_RECENT_CONVERSATIONS_PROMPT_LIMIT_RANGE.max;
      if (!Number.isFinite(parsed)) {
        return DEFAULT_RECENT_CONVERSATIONS_PROMPT_LIMIT;
      }
      return Math.max(min, Math.min(max, Math.round(parsed)));
    },
    applyPersonalizationMeta(payload: any) {
      if (payload && typeof payload.thinking_interval_default === 'number') {
        this.thinkingIntervalDefault = payload.thinking_interval_default;
      } else {
        this.thinkingIntervalDefault = DEFAULT_INTERVAL;
      }
      if (payload && payload.thinking_interval_range) {
        const { min, max } = payload.thinking_interval_range;
        this.thinkingIntervalRange = {
          min: typeof min === 'number' ? min : DEFAULT_INTERVAL_RANGE.min,
          max: typeof max === 'number' ? max : DEFAULT_INTERVAL_RANGE.max
        };
      } else {
        this.thinkingIntervalRange = { ...DEFAULT_INTERVAL_RANGE };
      }
      if (payload && payload.recent_conversations_prompt_limit_range) {
        const { min, max } = payload.recent_conversations_prompt_limit_range;
        this.recentConversationsPromptLimitRange = {
          min: typeof min === 'number' ? min : DEFAULT_RECENT_CONVERSATIONS_PROMPT_LIMIT_RANGE.min,
          max: typeof max === 'number' ? max : DEFAULT_RECENT_CONVERSATIONS_PROMPT_LIMIT_RANGE.max
        };
      } else {
        this.recentConversationsPromptLimitRange = {
          ...DEFAULT_RECENT_CONVERSATIONS_PROMPT_LIMIT_RANGE
        };
      }
      if (payload && Array.isArray(payload.tool_categories)) {
        this.toolCategories = payload.tool_categories
          .map((item: { id?: string; label?: string } = {}) => ({
            id: typeof item.id === 'string' ? item.id : String(item.id ?? ''),
            label:
              (item.label && String(item.label)) ||
              (typeof item.id === 'string' ? item.id : String(item.id ?? ''))
          }))
          .filter((item: { id: string }) => !!item.id);
      } else {
        this.toolCategories = [];
      }
      if (payload && Array.isArray(payload.skills_catalog)) {
        this.skillsCatalog = payload.skills_catalog
          .map((item: { id?: string; label?: string; description?: string } = {}) => ({
            id: typeof item.id === 'string' ? item.id : String(item.id ?? ''),
            label:
              (item.label && String(item.label)) ||
              (typeof item.id === 'string' ? item.id : String(item.id ?? '')),
            description: typeof item.description === 'string' ? item.description : undefined
          }))
          .filter((item: { id: string }) => !!item.id);
      } else {
        this.skillsCatalog = [];
      }
    },
    clearFeedback() {
      this.status = '';
      this.error = '';
    },
    async toggleEnabled() {
      if (this.toggleUpdating) {
        return;
      }
      const newValue = !this.form.enabled;
      const previousValue = this.form.enabled;
      this.toggleUpdating = true;
      this.status = '';
      this.error = '';
      this.form.enabled = newValue;
      try {
        const resp = await fetch('/api/personalization', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ enabled: newValue })
        });
        const result = await resp.json();
        if (!resp.ok || !result.success) {
          throw new Error(result.error || '更新失败');
        }
        if (result.data) {
          this.applyPersonalizationData(result.data);
        }
        this.applyPersonalizationMeta(result);
        const statusLabel = newValue ? '已启用' : '已停用';
        this.status = statusLabel;
        setTimeout(() => {
          if (this.status === statusLabel) {
            this.status = '';
          }
        }, 2000);
      } catch (error: any) {
        this.form.enabled = previousValue;
        this.error = error?.message || '更新失败';
      } finally {
        this.toggleUpdating = false;
      }
    },
    async save() {
      if (this.saving) {
        return;
      }
      this.saving = true;
      this.status = '';
      this.error = '';
      try {
        const shallowTrigger =
          this.normalizeCompressionNumber(this.form.shallow_compress_trigger_tokens) ??
          DEFAULT_SHALLOW_COMPRESS_TRIGGER_TOKENS;
        const deepTrigger =
          this.normalizeCompressionNumber(this.form.deep_compress_trigger_tokens) ??
          DEFAULT_DEEP_COMPRESS_TRIGGER_TOKENS;
        if (deepTrigger <= shallowTrigger) {
          throw new Error('深压缩触发上下文必须大于浅压缩触发上下文');
        }
        const resp = await fetch('/api/personalization', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(this.form)
        });
        const result = await resp.json();
        if (!resp.ok || !result.success) {
          throw new Error(result.error || '保存失败');
        }
        this.applyPersonalizationData(result.data || {});
        this.applyPersonalizationMeta(result);
        this.status = '已保存';
        setTimeout(() => {
          if (this.status === '已保存') {
            this.status = '';
          }
        }, 3000);
      } catch (error: any) {
        this.error = error?.message || '保存失败';
      } finally {
        this.saving = false;
      }
    },
    updateField(payload: { key: keyof PersonalForm; value: any }) {
      if (!payload || !payload.key) {
        return;
      }
      this.form = {
        ...this.form,
        [payload.key]: payload.value
      };
      if (payload.key === 'stacked_hide_borders') {
        persistStackedHideBorders(!!payload.value);
      }
      if (payload.key === 'minimal_expand_height_limited') {
        persistMinimalExpandHeightLimited(!!payload.value);
      }
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    /** 防抖自动保存：500ms 内多次调用只执行最后一次 */
    scheduleAutoSave() {
      if (autoSaveTimer) {
        clearTimeout(autoSaveTimer);
      }
      autoSaveTimer = setTimeout(() => {
        autoSaveTimer = null;
        this.autoSave();
      }, 500);
    },
    /** 静默自动保存，成功不显示提示，失败显示错误 */
    async autoSave() {
      if (this.saving) {
        return;
      }
      this.saving = true;
      try {
        const resp = await fetch('/api/personalization', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify(this.form)
        });
        const result = await resp.json();
        if (!resp.ok || !result.success) {
          throw new Error(result.error || '自动保存失败');
        }
        // 静默成功，不刷新表单（避免打断用户编辑）
      } catch (error: any) {
        this.error = error?.message || '自动保存失败';
      } finally {
        this.saving = false;
      }
    },
    setThinkingInterval(value: number | null) {
      let target: number | null = value;
      if (typeof target === 'number') {
        if (Number.isNaN(target)) {
          target = null;
        } else {
          const rounded = Math.round(target);
          const min = this.thinkingIntervalRange.min ?? DEFAULT_INTERVAL_RANGE.min;
          const max = this.thinkingIntervalRange.max ?? DEFAULT_INTERVAL_RANGE.max;
          target = Math.max(min, Math.min(max, rounded));
          if (target === this.thinkingIntervalDefault) {
            target = null;
          }
        }
      }
      this.form = {
        ...this.form,
        thinking_interval: target
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    setRecentConversationsPromptLimit(value: number | null) {
      const target =
        value === null || typeof value === 'undefined'
          ? DEFAULT_RECENT_CONVERSATIONS_PROMPT_LIMIT
          : this.normalizeRecentConversationsPromptLimit(value);
      this.form = {
        ...this.form,
        recent_conversations_prompt_limit: target
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    toggleDefaultToolCategory(categoryId: string) {
      if (!categoryId) {
        return;
      }
      const current = new Set(this.form.disabled_tool_categories || []);
      if (current.has(categoryId)) {
        current.delete(categoryId);
      } else {
        current.add(categoryId);
      }
      this.form = {
        ...this.form,
        disabled_tool_categories: Array.from(current)
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    toggleSkill(skillId: string) {
      if (!skillId) {
        return;
      }
      const current = new Set(this.form.enabled_skills || []);
      if (current.has(skillId)) {
        current.delete(skillId);
      } else {
        current.add(skillId);
      }
      this.form = {
        ...this.form,
        enabled_skills: Array.from(current)
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    setDefaultRunMode(mode: RunMode | null) {
      let target: RunMode | null = null;
      if (typeof mode === 'string' && RUN_MODE_OPTIONS.includes(mode as RunMode)) {
        target = mode as RunMode;
      }
      this.form = {
        ...this.form,
        default_run_mode: target
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    setDefaultPermissionMode(mode: PermissionMode) {
      const allowed: PermissionMode[] = ['readonly', 'approval', 'auto_approval', 'unrestricted'];
      const target = allowed.includes(mode) ? mode : 'unrestricted';
      this.form = {
        ...this.form,
        default_permission_mode: target
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    setVersioningRestoreMode(_mode: 'overwrite') {
      const target: 'overwrite' = 'overwrite';
      this.form = {
        ...this.form,
        versioning_restore_mode: target
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    setVersioningBackupMode(mode: VersioningBackupMode) {
      const target: VersioningBackupMode = mode === 'full' ? 'full' : 'shallow';
      this.form = {
        ...this.form,
        versioning_backup_mode: target
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    setDefaultModel(model: string | null) {
      const modelStore = useModelStore();
      const allowed = new Set((modelStore.models || []).map((m) => m.key));
      const target = typeof model === 'string' && allowed.has(model) ? model : null;
      this.form = {
        ...this.form,
        default_model: target
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    setImageCompression(mode: string) {
      const allowed = ['original', '1080p', '720p', '540p'];
      if (!allowed.includes(mode)) return;
      this.form = {
        ...this.form,
        image_compression: mode
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    applyTonePreset(preset: string) {
      if (!preset) {
        return;
      }
      this.form = {
        ...this.form,
        tone: preset
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    updateConsiderations(value: string) {
      this.form = {
        ...this.form,
        considerations: value
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    async logout() {
      try {
        console.info('[auth-debug] logout clicked, sending POST /logout');
        const resp = await fetch('/logout', {
          method: 'POST',
          credentials: 'same-origin',
          cache: 'no-store'
        });
        console.info('[auth-debug] logout POST status:', resp.status);
        let payload: any = null;
        try {
          payload = await resp.json();
        } catch (_err) {
          payload = null;
        }
        console.info('[auth-debug] logout POST payload:', payload);
        if (resp.ok && (!payload || payload.success !== false)) {
          window.location.replace(`/login?logged_out=1&ts=${Date.now()}`);
          return;
        }
        // 接口失败时，走 GET /logout 做兜底清理
        window.location.replace(`/logout?ts=${Date.now()}`);
      } catch (error: any) {
        console.error('退出登录失败:', error);
        this.error = error?.message || '退出登录失败，请稍后重试';
        // 兜底：直接访问 GET /logout
        window.location.replace(`/logout?ts=${Date.now()}`);
      }
    },
    persistExperiments() {
      if (typeof window === 'undefined' || !window.localStorage) {
        return;
      }
      try {
        window.localStorage.setItem(EXPERIMENT_STORAGE_KEY, JSON.stringify(this.experiments));
      } catch (error) {
        console.warn('写入实验功能设置失败：', error);
      }
    },
    setBlockDisplayMode(mode: BlockDisplayMode) {
      this.experiments = {
        ...this.experiments,
        blockDisplayMode: mode
      };
      this.persistExperiments();
      this.form = {
        ...this.form,
        block_display_mode: mode
      };
      this.scheduleAutoSave();
    },
    setCompactMessageDisplay(mode: CompactMessageDisplay) {
      const target: CompactMessageDisplay = mode === 'brief' ? 'brief' : 'full';
      this.form = {
        ...this.form,
        compact_message_display: target
      };
      // 同步旧版 localStorage 镜像，保持兼容并避免迁移逻辑回写旧值
      this.experiments = {
        ...this.experiments,
        compactMessageDisplay: target
      };
      this.persistExperiments();
      this.clearFeedback();
      // 持久化到后端配置文件（即时保存，参照主题/默认隐藏工作区）
      void this.persistCompactMessageDisplay(target);
    },
    async persistCompactMessageDisplay(mode: CompactMessageDisplay) {
      try {
        const resp = await fetch('/api/personalization', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ compact_message_display: mode })
        });
        const result = await resp.json();
        if (!resp.ok || !result.success) {
          console.warn('保存简略消息显示失败:', result?.error);
        }
      } catch (error) {
        console.warn('保存简略消息显示失败:', error);
      }
    },
    setCommunicationStyle(style: CommunicationStyle) {
      this.form = {
        ...this.form,
        communication_style: style
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    },
    setConversationContinuity(value: ConversationContinuity) {
      this.form = {
        ...this.form,
        conversation_continuity: value
      };
      this.clearFeedback();
      this.scheduleAutoSave();
    }
  }
});
