import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { promises as fs } from 'fs';
import path from 'path';
import os from 'os';
import { KanbanDataStore } from '../store.js';

describe('KanbanDataStore Integration Tests', () => {
  let store: KanbanDataStore;
  let tempDir: string;

  beforeEach(async () => {
    // Create a temporary directory for testing
    tempDir = await fs.mkdtemp(path.join(os.tmpdir(), 'kanban-test-'));
    
    // Create a mock ConfigManager that returns our temp directory
    const mockConfigManager = {
      getStoragePath: () => tempDir,
      getStorageManager: () => ({
        ensureStorageDirectories: async () => {},
        loadData: async () => null,
        saveData: async () => {}
      })
    } as any;
    
    store = new KanbanDataStore(mockConfigManager);
    await store.init();
  });

  afterEach(async () => {
    // Clean up temporary directory
    try {
      await fs.rm(tempDir, { recursive: true, force: true });
    } catch (error) {
      // Ignore cleanup errors
    }
  });

  describe('Board Management', () => {
    it('should create and persist a board', async () => {
      const board = store.createBoard('Test Board', ['To Do', 'Done']);
      await store.save();

      // Create a new store instance to verify persistence
      const mockConfigManager = {
        getStoragePath: () => tempDir,
        getStorageManager: () => ({
          ensureStorageDirectories: async () => {},
          loadData: async () => ({ boards: [board] }),
          saveData: async () => {}
        })
      } as any;
      const newStore = new KanbanDataStore(mockConfigManager);
      await newStore.init();

      const loadedBoard = newStore.getBoard('Test Board');
      expect(loadedBoard).toBeDefined();
      expect(loadedBoard?.name).toBe('Test Board');
      expect(loadedBoard?.columns).toEqual(['To Do', 'Done']);
    });

    it('should handle multiple boards', async () => {
      store.createBoard('Board 1');
      store.createBoard('Board 2');
      store.createBoard('Board 3');
      await store.save();

      const boards = store.getAllBoards();
      expect(boards).toHaveLength(3);
      expect(boards.map(b => b.name)).toContain('Board 1');
      expect(boards.map(b => b.name)).toContain('Board 2');
      expect(boards.map(b => b.name)).toContain('Board 3');
    });
  });

  describe('Task Management', () => {
    it('should add tasks to a board', async () => {
      const board = store.createBoard('Task Board');
      
      const task1 = store.addTask('Task Board', {
        title: 'First Task',
        description: 'Description 1',
        column: 'Backlog',
        priority: 'high',
      });

      const task2 = store.addTask('Task Board', {
        title: 'Second Task',
        description: 'Description 2',
        column: 'To Do',
        priority: 'medium',
      });

      await store.save();

      const updatedBoard = store.getBoard('Task Board');
      expect(updatedBoard?.tasks).toHaveLength(2);
      expect(updatedBoard?.tasks[0].title).toBe('First Task');
      expect(updatedBoard?.tasks[1].title).toBe('Second Task');
    });

    it('should move tasks between columns', async () => {
      const board = store.createBoard('Move Test Board');
      const task = store.addTask('Move Test Board', {
        title: 'Movable Task',
        column: 'Backlog',
        priority: 'medium',
      });

      expect(task?.column).toBe('Backlog');

      const success = store.moveTask('Move Test Board', task!.id, 'In Progress');
      expect(success).toBe(true);

      const updatedBoard = store.getBoard('Move Test Board');
      const movedTask = updatedBoard?.tasks.find(t => t.id === task!.id);
      expect(movedTask?.column).toBe('In Progress');
    });

    it('should update task properties', async () => {
      const board = store.createBoard('Update Test Board');
      const task = store.addTask('Update Test Board', {
        title: 'Original Title',
        column: 'Backlog',
        priority: 'low',
      });

      const success = store.updateTask('Update Test Board', task!.id, {
        title: 'Updated Title',
        priority: 'high',
        assignee: 'John Doe',
        labels: ['urgent', 'bug'],
      });

      expect(success).toBe(true);

      const updatedBoard = store.getBoard('Update Test Board');
      const updatedTask = updatedBoard?.tasks.find(t => t.id === task!.id);
      
      expect(updatedTask?.title).toBe('Updated Title');
      expect(updatedTask?.priority).toBe('high');
      expect(updatedTask?.assignee).toBe('John Doe');
      expect(updatedTask?.labels).toEqual(['urgent', 'bug']);
    });

    it('should delete tasks', async () => {
      const board = store.createBoard('Delete Test Board');
      const task1 = store.addTask('Delete Test Board', {
        title: 'Task to Keep',
        column: 'Backlog',
        priority: 'medium',
      });
      const task2 = store.addTask('Delete Test Board', {
        title: 'Task to Delete',
        column: 'Backlog',
        priority: 'medium',
      });

      expect(store.getBoard('Delete Test Board')?.tasks).toHaveLength(2);

      const success = store.deleteTask('Delete Test Board', task2!.id);
      expect(success).toBe(true);

      const updatedBoard = store.getBoard('Delete Test Board');
      expect(updatedBoard?.tasks).toHaveLength(1);
      expect(updatedBoard?.tasks[0].id).toBe(task1!.id);
    });
  });

  describe('Error Handling', () => {
    it('should return null when adding task to non-existent board', () => {
      const task = store.addTask('Non-existent Board', {
        title: 'Test',
        column: 'Backlog',
        priority: 'medium',
      });
      expect(task).toBeNull();
    });

    it('should return false when moving task in non-existent board', () => {
      const success = store.moveTask('Non-existent Board', 'task-id', 'Done');
      expect(success).toBe(false);
    });

    it('should return false when moving to invalid column', () => {
      const board = store.createBoard('Column Test Board');
      const task = store.addTask('Column Test Board', {
        title: 'Test',
        column: 'Backlog',
        priority: 'medium',
      });

      const success = store.moveTask('Column Test Board', task!.id, 'Invalid Column');
      expect(success).toBe(false);
    });
  });
});