import * as fs from 'fs';
import * as os from 'os';
import * as path from 'path';
import { afterEach, describe, expect, it } from 'vitest';

import { TeamAttachmentStore } from '../../../src/main/services/team/TeamAttachmentStore';
import { TeamTaskAttachmentStore } from '../../../src/main/services/team/TeamTaskAttachmentStore';
import {
  type ElectronUserDataMigrationApp,
  getLegacyElectronUserDataCandidates,
  migrateElectronUserDataDirectory,
  shouldCopyElectronUserDataEntry,
} from '../../../src/main/utils/electronUserDataMigration';
import {
  getAppDataPath,
  getBackupsBasePath,
  getMcpConfigsBasePath,
  getMcpServerBasePath,
  setAppDataBasePath,
} from '../../../src/main/utils/pathDecoder';

class FakeElectronApp implements ElectronUserDataMigrationApp {
  setPathCalls: { name: string; value: string }[] = [];

  constructor(private userDataPath: string) {}

  getPath(name: string): string {
    if (name !== 'userData' && name !== 'sessionData') {
      throw new Error(`Unexpected path lookup: ${name}`);
    }
    return this.userDataPath;
  }

  setPath(name: string, value: string): void {
    this.setPathCalls.push({ name, value });
    if (name === 'userData' || name === 'sessionData') {
      this.userDataPath = value;
    }
  }
}

describe('electron userData migration', () => {
  const tempDirs: string[] = [];

  afterEach(() => {
    setAppDataBasePath(null);
    while (tempDirs.length > 0) {
      const tempDir = tempDirs.pop();
      if (tempDir) {
        fs.rmSync(tempDir, { recursive: true, force: true });
      }
    }
  });

  function createTempRoot(): string {
    const tempRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'electron-user-data-migration-'));
    tempDirs.push(tempRoot);
    return tempRoot;
  }

  function writeFile(root: string, relativePath: string, content: string): void {
    const filePath = path.join(root, relativePath);
    fs.mkdirSync(path.dirname(filePath), { recursive: true });
    fs.writeFileSync(filePath, content, 'utf8');
  }

  function readFile(root: string, relativePath: string): string {
    return fs.readFileSync(path.join(root, relativePath), 'utf8');
  }

  it('derives legacy candidates beside the current Electron userData directory', () => {
    const currentPath = path.join('/Users/me/Library/Application Support', 'Agent Teams UI');
    const parentPath = path.dirname(currentPath);

    expect(getLegacyElectronUserDataCandidates(currentPath)).toEqual([
      path.join(parentPath, 'agent-teams-ai'),
      path.join(parentPath, 'Agent Teams AI'),
      path.join(parentPath, 'Claude Agent Teams UI'),
      path.join(parentPath, 'claude-agent-teams-ui'),
      path.join(parentPath, 'claude-devtools'),
      path.join(parentPath, 'claude-code-context'),
    ]);
  });

  it('reuses populated legacy userData by default instead of copying it during startup', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'claude-agent-teams-ui');
    const currentPath = path.join(root, 'agent-teams-ai');
    const app = new FakeElectronApp(currentPath);

    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');

    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath,
      legacyPath,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-reused',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: legacyPath },
      { name: 'sessionData', value: legacyPath },
    ]);
    expect(fs.existsSync(currentPath)).toBe(false);
  });

  it('does not invoke the copy migration in the default startup strategy', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'claude-agent-teams-ui');
    const currentPath = path.join(root, 'agent-teams-ai');
    const app = new FakeElectronApp(currentPath);

    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');

    const result = migrateElectronUserDataDirectory(app, {
      copyDirectory: () => {
        throw new Error('copy should not run during default startup');
      },
    });

    expect(result).toMatchObject({
      currentPath,
      legacyPath,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-reused',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: legacyPath },
      { name: 'sessionData', value: legacyPath },
    ]);
    expect(fs.existsSync(currentPath)).toBe(false);
  });

  it('does not treat a cache-only new userData directory as populated', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'claude-agent-teams-ui');
    const currentPath = path.join(root, 'agent-teams-ai');
    const app = new FakeElectronApp(currentPath);

    writeFile(currentPath, 'Cache/Cache_Data/blob', 'cache');
    writeFile(currentPath, 'Code Cache/js/cache', 'code cache');
    writeFile(currentPath, 'Partitions/dev/Cache/Cache_Data/blob', 'partition cache');
    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');

    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath,
      legacyPath,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-reused',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: legacyPath },
      { name: 'sessionData', value: legacyPath },
    ]);
  });

  it('does not treat Electron-generated shell files as populated new userData', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'claude-agent-teams-ui');
    const currentPath = path.join(root, 'agent-teams-ai');
    const app = new FakeElectronApp(currentPath);

    writeFile(currentPath, 'Preferences', '{}');
    writeFile(currentPath, 'Cookies', 'sqlite bytes');
    writeFile(currentPath, 'DIPS', 'tracking state');
    writeFile(currentPath, 'WebStorage/QuotaManager', 'quota');
    writeFile(currentPath, '.updaterId', 'updater');
    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');

    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath,
      legacyPath,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-reused',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: legacyPath },
      { name: 'sessionData', value: legacyPath },
    ]);
  });

  it('does not treat regenerated runtime-only folders as completed migration evidence', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'claude-agent-teams-ui');
    const currentPath = path.join(root, 'agent-teams-ai');
    const app = new FakeElectronApp(currentPath);

    writeFile(currentPath, 'opencode-bridge/production-e2e-evidence.json', '{}');
    writeFile(currentPath, 'mcp-server/1.3.0/index.js', 'console.log("generated")');
    writeFile(currentPath, 'mcp-configs/agent-teams-mcp-generated.json', '{}');
    writeFile(currentPath, 'Local Storage/leveldb/000003.log', 'renderer local storage');
    writeFile(currentPath, 'IndexedDB/http_localhost_5173.indexeddb.leveldb/000003.log', 'idb');
    writeFile(currentPath, 'Partitions/dev/Local Storage/leveldb/000003.log', 'partition state');
    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');

    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath,
      legacyPath,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-reused',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: legacyPath },
      { name: 'sessionData', value: legacyPath },
    ]);
  });

  it('keeps a populated new userData directory after a completed migration', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'claude-agent-teams-ui');
    const currentPath = path.join(root, 'agent-teams-ai');
    const app = new FakeElectronApp(currentPath);

    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');
    writeFile(currentPath, 'data/attachments/team-a/current.txt', 'current');
    writeFile(currentPath, 'backups/registry.json', '{}');

    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath,
      legacyPath: null,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'current-populated',
    });
    expect(app.setPathCalls).toEqual([]);
  });

  it('prefers an already populated agent-teams-ai directory over older legacy data', () => {
    const root = createTempRoot();
    const completedNewPath = path.join(root, 'agent-teams-ai');
    const olderLegacyPath = path.join(root, 'claude-agent-teams-ui');
    const currentPath = path.join(root, 'Agent Teams UI');
    const app = new FakeElectronApp(currentPath);

    writeFile(currentPath, 'opencode-bridge/production-e2e-evidence.json', '{}');
    writeFile(completedNewPath, 'data/attachments/team-a/current.txt', 'current');
    writeFile(olderLegacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');

    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath,
      legacyPath: completedNewPath,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-reused',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: completedNewPath },
      { name: 'sessionData', value: completedNewPath },
    ]);
  });

  it('uses populated agent-teams-ai when both current product-name and new package-name paths exist', () => {
    const root = createTempRoot();
    const completedNewPath = path.join(root, 'agent-teams-ai');
    const currentProductPath = path.join(root, 'Agent Teams UI');
    const app = new FakeElectronApp(currentProductPath);

    writeFile(currentProductPath, 'data/attachments/team-a/old.txt', 'old');
    writeFile(completedNewPath, 'data/attachments/team-a/current.txt', 'current');

    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath: currentProductPath,
      legacyPath: completedNewPath,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-reused',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: completedNewPath },
      { name: 'sessionData', value: completedNewPath },
    ]);
    expect(readFile(completedNewPath, 'data/attachments/team-a/current.txt')).toBe('current');
    expect(readFile(currentProductPath, 'data/attachments/team-a/old.txt')).toBe('old');
  });

  it('reuses existing agent-teams-ai data when the current product name is Agent Teams AI', () => {
    const root = createTempRoot();
    const completedNewPath = path.join(root, 'agent-teams-ai');
    const currentProductPath = path.join(root, 'Agent Teams AI');
    const olderProductPath = path.join(root, 'Agent Teams UI');
    const app = new FakeElectronApp(currentProductPath);

    writeFile(currentProductPath, 'Preferences', '{}');
    writeFile(completedNewPath, 'data/attachments/team-a/current.txt', 'current');
    writeFile(olderProductPath, 'data/attachments/team-a/old.txt', 'old');

    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath: currentProductPath,
      legacyPath: completedNewPath,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-reused',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: completedNewPath },
      { name: 'sessionData', value: completedNewPath },
    ]);
    expect(readFile(completedNewPath, 'data/attachments/team-a/current.txt')).toBe('current');
    expect(readFile(olderProductPath, 'data/attachments/team-a/old.txt')).toBe('old');
  });

  it('copies legacy app-owned state and durable renderer storage without Chromium caches', async () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'Claude Agent Teams UI');
    const currentPath = path.join(root, 'Agent Teams UI');
    fs.mkdirSync(currentPath, { recursive: true });

    const knownFiles = [
      [
        'data/attachments/team-a/msg-1/_index.json',
        '[{"id":"att-1","filename":"note.txt","mimeType":"text/plain"}]',
      ],
      ['data/attachments/team-a/msg-1/att-1--note.txt', 'message attachment'],
      ['data/task-attachments/team-a/task-1/task-att-1--task.txt', 'task attachment'],
      ['backups/registry.json', '{"version":1,"teams":{}}'],
      ['backups/teams/team-a/manifest.json', '{"version":1}'],
      ['mcp-configs/agent-teams-mcp-old.json', '{"mcpServers":{}}'],
      ['mcp-server/1.3.0/index.js', 'console.log("mcp")'],
      ['mcp-server/1.3.0/package.json', '{"type":"module"}'],
      ['opencode-bridge/command-ledger.json', '{"commands":[]}'],
      ['opencode-bridge/command-leases.json', '{"leases":[]}'],
      ['logs/claude-cli-auth-diag.ndjson', '{"event":"auth"}\n'],
      ['Local Storage/leveldb/000003.log', 'renderer localStorage bytes'],
      ['IndexedDB/http_localhost_5173.indexeddb.leveldb/000003.log', 'renderer indexeddb bytes'],
      ['Partitions/dev/Local Storage/leveldb/000003.log', 'dev partition localStorage bytes'],
      [
        'Partitions/dev/IndexedDB/http_localhost_5173.indexeddb.leveldb/000003.log',
        'dev partition indexeddb bytes',
      ],
      ['future-feature/state.json', '{"kept":true}'],
    ] as const;
    const transientFiles = [
      ['Cache/Cache_Data/blob', 'http cache'],
      ['Code Cache/js/cache', 'code cache'],
      ['GPUCache/data_0', 'gpu cache'],
      ['DawnGraphiteCache/data_0', 'graphite cache'],
      ['DawnWebGPUCache/data_0', 'webgpu cache'],
      ['Crashpad/settings.dat', 'crashpad state'],
      ['Session Storage/000003.log', 'session storage'],
      ['Local Storage/leveldb/LOCK', 'stale leveldb lock'],
      ['IndexedDB/http_localhost_5173.indexeddb.leveldb/LOCK', 'stale indexeddb lock'],
      ['Network Persistent State', 'network state'],
      ['DIPS', 'tracking protection state'],
      ['Trust Tokens', 'trust tokens'],
      ['Partitions/dev/Cache/Cache_Data/blob', 'partition http cache'],
      ['Partitions/dev/Code Cache/js/cache', 'partition code cache'],
      ['Partitions/dev/GPUCache/data_0', 'partition gpu cache'],
      ['Partitions/dev/Session Storage/000003.log', 'partition session storage'],
    ] as const;

    for (const [relativePath, content] of knownFiles) {
      writeFile(legacyPath, relativePath, content);
    }
    for (const [relativePath, content] of transientFiles) {
      writeFile(legacyPath, relativePath, content);
    }

    const result = migrateElectronUserDataDirectory(new FakeElectronApp(currentPath), {
      strategy: 'copy',
    });

    expect(result).toMatchObject({
      currentPath,
      legacyPath,
      migrated: true,
      fallbackToLegacy: false,
      reason: 'migrated',
    });
    expect(fs.existsSync(legacyPath)).toBe(true);
    for (const [relativePath, content] of knownFiles) {
      expect(readFile(currentPath, relativePath)).toBe(content);
    }
    for (const [relativePath] of transientFiles) {
      expect(fs.existsSync(path.join(currentPath, relativePath))).toBe(false);
    }

    setAppDataBasePath(currentPath);
    expect(getAppDataPath()).toBe(path.join(currentPath, 'data'));
    expect(getBackupsBasePath()).toBe(path.join(currentPath, 'backups'));
    expect(getMcpConfigsBasePath()).toBe(path.join(currentPath, 'mcp-configs'));
    expect(getMcpServerBasePath()).toBe(path.join(currentPath, 'mcp-server'));

    const messageAttachments = await new TeamAttachmentStore().getAttachments('team-a', 'msg-1');
    expect(messageAttachments).toEqual([
      {
        id: 'att-1',
        data: Buffer.from('message attachment').toString('base64'),
        mimeType: 'text/plain',
        filePath: path.join(currentPath, 'data', 'attachments', 'team-a', 'msg-1', 'att-1--note.txt'),
      },
    ]);

    await expect(
      new TeamTaskAttachmentStore().getAttachment('team-a', 'task-1', 'task-att-1', 'text')
    ).resolves.toBe(Buffer.from('task attachment').toString('base64'));
  });

  it('keeps unknown durable state but skips transient Chromium cache entries', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'Claude Agent Teams UI');

    expect(
      shouldCopyElectronUserDataEntry(legacyPath, path.join(legacyPath, 'data/state.json'))
    ).toBe(true);
    expect(
      shouldCopyElectronUserDataEntry(
        legacyPath,
        path.join(legacyPath, 'future-feature/state.json')
      )
    ).toBe(true);
    expect(
      shouldCopyElectronUserDataEntry(
        legacyPath,
        path.join(legacyPath, 'Partitions/dev/Local Storage/leveldb/000003.log')
      )
    ).toBe(true);
    expect(
      shouldCopyElectronUserDataEntry(
        legacyPath,
        path.join(legacyPath, 'Partitions/dev/Cache/Cache_Data/blob')
      )
    ).toBe(false);
    expect(
      shouldCopyElectronUserDataEntry(
        legacyPath,
        path.join(legacyPath, 'Local Storage/leveldb/LOCK')
      )
    ).toBe(false);
  });

  it('does not merge legacy data into an already populated new userData directory', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'Claude Agent Teams UI');
    const currentPath = path.join(root, 'Agent Teams UI');

    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');
    writeFile(currentPath, 'data/attachments/team-a/current.txt', 'current');

    const result = migrateElectronUserDataDirectory(new FakeElectronApp(currentPath));

    expect(result).toMatchObject({
      currentPath,
      legacyPath: null,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'current-populated',
    });
    expect(readFile(currentPath, 'data/attachments/team-a/current.txt')).toBe('current');
    expect(fs.existsSync(path.join(currentPath, 'data/attachments/team-a/legacy.txt'))).toBe(false);
  });

  it('falls back to the legacy userData path for this run when copying fails', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'Claude Agent Teams UI');
    const currentPath = path.join(root, 'Agent Teams UI');
    const app = new FakeElectronApp(currentPath);

    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');
    const result = migrateElectronUserDataDirectory(app, {
      strategy: 'copy',
      copyDirectory: () => {
        throw new Error('copy denied');
      },
    });

    expect(result).toMatchObject({
      currentPath,
      legacyPath,
      migrated: false,
      fallbackToLegacy: true,
      reason: 'legacy-fallback',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: legacyPath },
      { name: 'sessionData', value: legacyPath },
    ]);
  });

  it('uses the new populated userData path if another startup finishes migration first', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'Claude Agent Teams UI');
    const currentPath = path.join(root, 'Agent Teams UI');
    const app = new FakeElectronApp(currentPath);

    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');

    const result = migrateElectronUserDataDirectory(app, {
      strategy: 'copy',
      copyDirectory: () => {
        writeFile(currentPath, 'data/attachments/team-a/current.txt', 'current');
        throw new Error('destination appeared');
      },
    });

    expect(result).toMatchObject({
      currentPath,
      legacyPath: null,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'current-populated',
    });
    expect(app.setPathCalls).toEqual([]);
    expect(readFile(currentPath, 'data/attachments/team-a/current.txt')).toBe('current');
  });

  it('falls back to the legacy userData path when copying fails and new userData is still empty', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'Claude Agent Teams UI');
    const currentPath = path.join(root, 'Agent Teams UI');
    const app = new FakeElectronApp(currentPath);

    fs.mkdirSync(currentPath, { recursive: true });
    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');

    const result = migrateElectronUserDataDirectory(app, {
      strategy: 'copy',
      copyDirectory: () => {
        throw new Error('copy denied');
      },
    });

    expect(result).toMatchObject({
      currentPath,
      legacyPath,
      migrated: false,
      fallbackToLegacy: true,
      reason: 'legacy-fallback',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: legacyPath },
      { name: 'sessionData', value: legacyPath },
    ]);
  });

  it('does not fallback when the new userData path is a file', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'Claude Agent Teams UI');
    const currentPath = path.join(root, 'Agent Teams UI');

    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');
    fs.writeFileSync(currentPath, 'not a directory', 'utf8');

    const result = migrateElectronUserDataDirectory(new FakeElectronApp(currentPath));

    expect(result).toMatchObject({
      currentPath,
      legacyPath: null,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'current-path-exists',
    });
  });

  it('uses the lowercase package-name legacy directory when product-name durable data is absent', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'claude-agent-teams-ui');
    const currentPath = path.join(root, 'Agent Teams UI');

    writeFile(legacyPath, 'data/attachments/team-a/legacy.txt', 'legacy');

    const app = new FakeElectronApp(currentPath);
    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath,
      legacyPath,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-reused',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: legacyPath },
      { name: 'sessionData', value: legacyPath },
    ]);
    expect(fs.existsSync(path.join(currentPath, 'data/attachments/team-a/legacy.txt'))).toBe(
      false
    );
  });

  it('does not reuse non-durable legacy directories when no durable user data exists', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'claude-agent-teams-ui');
    const currentPath = path.join(root, 'Agent Teams UI');

    writeFile(legacyPath, 'mcp-configs/legacy.json', '{}');
    writeFile(legacyPath, 'opencode-bridge/command-ledger.json', '{"commands":[]}');
    writeFile(legacyPath, 'Local Storage/leveldb/000003.log', 'renderer local storage');

    const app = new FakeElectronApp(currentPath);
    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath,
      legacyPath: null,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-missing',
    });
    expect(app.setPathCalls).toEqual([]);
  });

  it('prefers populated older legacy data over an empty newer legacy directory', () => {
    const root = createTempRoot();
    const emptyNewerLegacyPath = path.join(root, 'Claude Agent Teams UI');
    const populatedOlderLegacyPath = path.join(root, 'claude-devtools');
    const currentPath = path.join(root, 'Agent Teams UI');

    fs.mkdirSync(emptyNewerLegacyPath, { recursive: true });
    writeFile(populatedOlderLegacyPath, 'data/attachments/team-a/pre-release.txt', 'pre-release');

    const app = new FakeElectronApp(currentPath);
    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath,
      legacyPath: populatedOlderLegacyPath,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-reused',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: populatedOlderLegacyPath },
      { name: 'sessionData', value: populatedOlderLegacyPath },
    ]);
    expect(fs.existsSync(path.join(currentPath, 'data/attachments/team-a/pre-release.txt'))).toBe(
      false
    );
  });

  it('uses the pre-1.0 claude-devtools legacy directory when newer legacy data is absent', () => {
    const root = createTempRoot();
    const legacyPath = path.join(root, 'claude-devtools');
    const currentPath = path.join(root, 'Agent Teams UI');

    writeFile(legacyPath, 'data/attachments/team-a/pre-release.txt', 'pre-release');

    const app = new FakeElectronApp(currentPath);
    const result = migrateElectronUserDataDirectory(app);

    expect(result).toMatchObject({
      currentPath,
      legacyPath,
      migrated: false,
      fallbackToLegacy: false,
      reason: 'legacy-reused',
    });
    expect(app.setPathCalls).toEqual([
      { name: 'userData', value: legacyPath },
      { name: 'sessionData', value: legacyPath },
    ]);
    expect(fs.existsSync(path.join(currentPath, 'data/attachments/team-a/pre-release.txt'))).toBe(
      false
    );
  });
});
