import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { StorageManager } from '../storage-manager.js';
import type { StorageConfig, ProjectMarker } from '../storage-manager.js';

describe('StorageManager', () => {
  let storageManager: StorageManager;
  let mockProjectRoot: string;

  beforeEach(() => {
    vi.clearAllMocks();
    mockProjectRoot = '/test/project/root';
    
    // Mock process.cwd()
    vi.spyOn(process, 'cwd').mockReturnValue(mockProjectRoot);
  });

  afterEach(() => {
    vi.restoreAllMocks();
  });

  describe('constructor', () => {
    it('should initialize with default config', () => {
      storageManager = new StorageManager();
      expect(storageManager).toBeInstanceOf(StorageManager);
    });

    it('should initialize with custom config', () => {
      const customConfig: Partial<StorageConfig> = {
        mode: 'user-home',
        autoSync: false,
        syncInterval: 60000,
      };
      
      storageManager = new StorageManager(customConfig);
      expect(storageManager).toBeInstanceOf(StorageManager);
    });
  });

  describe('getProjectRoot', () => {
    it('should return the project root', () => {
      storageManager = new StorageManager();
      const result = storageManager.getProjectRoot();
      expect(result).toBe(mockProjectRoot);
    });
  });

  describe('getProjectFilePath', () => {
    beforeEach(() => {
      storageManager = new StorageManager();
    });

    it('should return project file path', () => {
      const result = storageManager.getProjectFilePath('README.md');
      expect(result).toBe(`${mockProjectRoot}/README.md`);
    });

    it('should return project file path with subdirectory', () => {
      const result = storageManager.getProjectFilePath('docs', 'API.md');
      expect(result).toBe(`${mockProjectRoot}/docs/API.md`);
    });
  });

  // Integration tests that actually use the file system would go in a separate file
  // These tests focus on the logic that doesn't require file system access
  describe('project ID generation', () => {
    it('should generate project ID based on project name and path', () => {
      storageManager = new StorageManager();
      // Access private method through type assertion for testing
      const generateId = (storageManager as any).generateProjectId();
      expect(generateId).toMatch(/^root-[a-f0-9]{8}$/);
    });
  });

  describe('validation', () => {
    it('should detect when running in Atlas repo', () => {
      // Mock the atlasRoot to match projectRoot
      storageManager = new StorageManager();
      (storageManager as any).atlasRoot = mockProjectRoot;
      
      expect(storageManager.isRunningInAtlasRepo()).toBe(true);
    });

    it('should throw error when using project-local mode in Atlas repo', () => {
      storageManager = new StorageManager({ mode: 'project-local' });
      (storageManager as any).atlasRoot = mockProjectRoot;
      
      expect(() => storageManager.validateNotInAtlasRepo()).toThrow(
        'Cannot use project-local storage mode when running from Atlas repository'
      );
    });

    it('should not throw error when using user-home mode in Atlas repo', () => {
      storageManager = new StorageManager({ mode: 'user-home' });
      (storageManager as any).atlasRoot = mockProjectRoot;
      
      expect(() => storageManager.validateNotInAtlasRepo()).not.toThrow();
    });
  });
});