import test from 'node:test';
import assert from 'node:assert/strict';
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import {
  buildInitialUserMemoryProfile,
  buildTaskRoutingAgentText,
  resolveCodeExecutorRouting,
  renderCodeExecutorGuidance,
  suggestCodeExecutorForTask,
  buildSessionMemoryEntries,
  ensureUserMemoryProfile,
  hasMemoryStore,
  loadUserMemoryProfile,
  renderMemoryStoreGuidance,
  USER_MEMORY_PROFILE_FILENAME,
} from './user-memory-profile.mjs';
import { buildAgentExtensionPolicy, DEFAULT_USER_CAPABILITIES } from './capabilities.mjs';

test('DEFAULT_USER_CAPABILITIES enables memory_store (L3)', () => {
  assert.equal(DEFAULT_USER_CAPABILITIES.memory_store, true);
  assert.equal(DEFAULT_USER_CAPABILITIES.context_memory, true);
});

test('buildAgentExtensionPolicy adds builtin memory when memory_store is enabled', () => {
  const policy = buildAgentExtensionPolicy(DEFAULT_USER_CAPABILITIES);
  assert.ok(policy.extensionOverrides.some((ext) => ext.name === 'memory'));
  assert.ok(policy.extensionOverrides.some((ext) => ext.name === 'projectmemory'));
});

test('hasMemoryStore detects memory extension in session policy', () => {
  const policy = buildAgentExtensionPolicy({ ...DEFAULT_USER_CAPABILITIES, memory_store: false });
  assert.equal(hasMemoryStore(policy), false);
  assert.equal(hasMemoryStore(buildAgentExtensionPolicy(DEFAULT_USER_CAPABILITIES)), true);
});

test('ensureUserMemoryProfile creates and updates profile file', () => {
  const root = fs.mkdtempSync(path.join(os.tmpdir(), 'tkmind-profile-'));
  const first = ensureUserMemoryProfile(root, {
    userId: 'user-1',
    displayName: 'Alice',
    username: 'alice',
  });
  assert.equal(first.displayName, 'Alice');
  assert.equal(fs.existsSync(path.join(root, USER_MEMORY_PROFILE_FILENAME)), true);

  const updated = ensureUserMemoryProfile(root, {
    userId: 'user-1',
    displayName: '艾丽丝',
    username: 'alice',
  });
  assert.equal(updated.displayName, '艾丽丝');
  assert.equal(loadUserMemoryProfile(root)?.displayName, '艾丽丝');
});

test('buildSessionMemoryEntries injects sandbox, guidance, and profile', () => {
  const root = fs.mkdtempSync(path.join(os.tmpdir(), 'tkmind-memory-'));
  ensureUserMemoryProfile(root, {
    userId: 'user-2',
    displayName: 'Bob',
    username: 'bob',
  });
  const sessionPolicy = {
    ...buildAgentExtensionPolicy({
      ...DEFAULT_USER_CAPABILITIES,
      aider: true,
      openhands: true,
    }),
    policies: {
      code_delegate_executor: 'openhands',
      code_task_routing: 'split',
    },
  };
  const entries = buildSessionMemoryEntries({
    workingDir: root,
    sessionPolicy,
    sandboxConstraints: '## sandbox',
    userContext: { userId: 'user-2', displayName: 'Bob', username: 'bob' },
  });
  assert.equal(entries.length, 4);
  assert.equal(entries[0].title, 'TKMind 用户空间沙箱');
  assert.equal(entries[1].title, 'TKMind 代码委托策略');
  assert.match(entries[1].content, /openhands/);
  assert.match(entries[2].content, /长期记忆/);
  assert.match(entries[3].content, /Bob/);
});

test('renderMemoryStoreGuidance scopes memory to one user', () => {
  const text = renderMemoryStoreGuidance({ addressName: '小陈' });
  assert.match(text, /小陈/);
  assert.match(text, /不得与其他用户混淆/);
});

test('buildInitialUserMemoryProfile seeds defaults', () => {
  const profile = buildInitialUserMemoryProfile({
    userId: 'abc',
    displayName: '测试',
    username: 'tester',
  });
  assert.equal(profile.version, 1);
  assert.equal(profile.language, 'zh-CN');
  assert.equal(profile.responseStyle, 'balanced');
  assert.deepEqual(profile.preferences, []);
});

test('renderCodeExecutorGuidance reflects preferred executor and fallback', () => {
  const text = renderCodeExecutorGuidance({
    extensionOverrides: [
      { name: 'aider' },
      { name: 'openhands' },
    ],
    policies: {
      code_delegate_executor: 'aider',
      code_task_routing: 'force_aider',
    },
  });
  assert.match(text, /aider/i);
  assert.match(text, /openhands/i);
  assert.match(text, /优先使用/);
  assert.match(text, /统一走 `aider`/);
});

test('resolveCodeExecutorRouting falls back when preferred executor is unavailable', () => {
  const routing = resolveCodeExecutorRouting({
    extensionOverrides: [{ name: 'aider' }],
    policies: {
      code_delegate_executor: 'openhands',
      code_task_routing: 'split',
    },
  });
  assert.deepEqual(routing.available, ['aider']);
  assert.equal(routing.preferred, 'auto');
  assert.equal(routing.routing, 'split');
  assert.match(routing.rules[0], /auto/);
});

test('suggestCodeExecutorForTask prefers openhands for repo refactor style tasks', () => {
  const suggestion = suggestCodeExecutorForTask(
    '请帮我重构这个仓库里的认证流程，涉及多文件并跑一下测试',
    {
      extensionOverrides: [{ name: 'aider' }, { name: 'openhands' }],
      policies: { code_delegate_executor: 'auto', code_task_routing: 'split' },
    },
  );
  assert.equal(suggestion?.suggestedExecutor, 'openhands');
});

test('buildTaskRoutingAgentText preserves task body and adds hidden routing hint', () => {
  const text = buildTaskRoutingAgentText(
    '请修复这个按钮点击无效的 bug，改一下前端代码',
    {
      extensionOverrides: [{ name: 'aider' }, { name: 'openhands' }],
      policies: { code_delegate_executor: 'aider', code_task_routing: 'force_aider' },
    },
  );
  assert.match(text, /TKMind 路由提示/);
  assert.match(text, /aider/i);
  assert.match(text, /请修复这个按钮点击无效的 bug，改一下前端代码/);
});
