import { describe, it, expect, beforeEach, vi } from 'vitest';
import { KanbanDataStore } from '../store.js';
import { ConfigManager } from '../../../config/config-manager.js';
import { Task, KanbanBoard } from '../types.js';

vi.mock('../../../config/config-manager.js');

describe('Kanban Enhanced Features Tests', () => {
  let store: KanbanDataStore;
  let mockConfigManager: vi.Mocked<ConfigManager>;
  let board: KanbanBoard;

  beforeEach(async () => {
    mockConfigManager = new ConfigManager() as vi.Mocked<ConfigManager>;
    mockConfigManager.getStorageManager = vi.fn().mockReturnValue({
      loadData: vi.fn().mockResolvedValue(null),
      saveData: vi.fn().mockResolvedValue(undefined),
      ensureStorageDirectories: vi.fn().mockResolvedValue(undefined)
    });

    store = new KanbanDataStore(mockConfigManager);
    await store.init();
    board = store.createBoard('Test Board');
  });

  describe('Acceptance Criteria Management', () => {
    it('should add task with acceptance criteria', () => {
      const task = store.addTask('Test Board', {
        title: 'Implement feature',
        column: 'To Do',
        acceptanceCriteria: [
          {
            id: 'ac-1',
            description: 'Feature works correctly',
            status: 'pending'
          },
          {
            id: 'ac-2',
            description: 'Tests are passing',
            status: 'pending'
          }
        ]
      });

      expect(task).toBeDefined();
      expect(task!.acceptanceCriteria).toHaveLength(2);
      expect(task!.acceptanceCriteria[0].status).toBe('pending');
    });

    it('should update acceptance criterion status', () => {
      const task = store.addTask('Test Board', {
        title: 'Test task',
        column: 'To Do',
        acceptanceCriteria: [
          {
            id: 'ac-1',
            description: 'Criterion 1',
            status: 'pending'
          }
        ]
      });

      const criterion = task!.acceptanceCriteria[0];
      criterion.status = 'completed';
      criterion.verifiedBy = 'tester';
      criterion.verifiedAt = new Date();

      const success = store.updateTask('Test Board', task!.id, {
        acceptanceCriteria: [criterion]
      });

      expect(success).toBe(true);
      const updatedTask = board.tasks.find(t => t.id === task!.id);
      expect(updatedTask!.acceptanceCriteria[0].status).toBe('completed');
      expect(updatedTask!.acceptanceCriteria[0].verifiedBy).toBe('tester');
    });
  });

  describe('Task Dependencies', () => {
    it('should add task with dependencies', () => {
      const blockerTask = store.addTask('Test Board', {
        title: 'Blocker task',
        column: 'To Do'
      });

      const dependentTask = store.addTask('Test Board', {
        title: 'Dependent task',
        column: 'To Do',
        dependencies: [
          {
            taskId: blockerTask!.id,
            type: 'depends_on'
          }
        ]
      });

      expect(dependentTask!.dependencies).toHaveLength(1);
      expect(dependentTask!.dependencies[0].taskId).toBe(blockerTask!.id);
      expect(dependentTask!.dependencies[0].type).toBe('depends_on');
    });

    it('should handle circular dependencies check', () => {
      const task1 = store.addTask('Test Board', {
        title: 'Task 1',
        column: 'To Do'
      });

      const task2 = store.addTask('Test Board', {
        title: 'Task 2',
        column: 'To Do',
        dependencies: [{
          taskId: task1!.id,
          type: 'depends_on'
        }]
      });

      // This would need validation logic in the actual implementation
      // For now, we just verify the structure is correct
      expect(task2!.dependencies[0].taskId).toBe(task1!.id);
    });
  });

  describe('Time Tracking', () => {
    it('should add task with time estimate', () => {
      const task = store.addTask('Test Board', {
        title: 'Timed task',
        column: 'To Do',
        timeTracking: {
          estimated: 8
        }
      });

      expect(task!.timeTracking).toBeDefined();
      expect(task!.timeTracking!.estimated).toBe(8);
    });

    it('should track time spent on task', () => {
      const task = store.addTask('Test Board', {
        title: 'Task',
        column: 'To Do',
        timeTracking: {
          estimated: 8
        }
      });

      const success = store.updateTask('Test Board', task!.id, {
        timeTracking: {
          estimated: 8,
          spent: 3,
          logs: [{
            date: new Date(),
            hours: 3,
            description: 'Initial work'
          }]
        }
      });

      expect(success).toBe(true);
      const updatedTask = board.tasks.find(t => t.id === task!.id);
      expect(updatedTask!.timeTracking!.spent).toBe(3);
      expect(updatedTask!.timeTracking!.logs).toHaveLength(1);
    });
  });

  describe('Tags Management', () => {
    it('should use tags instead of labels', () => {
      const task = store.addTask('Test Board', {
        title: 'Tagged task',
        column: 'To Do',
        tags: ['frontend', 'urgent']
      });

      expect(task!.tags).toEqual(['frontend', 'urgent']);
    });

    it('should support legacy labels property', () => {
      const task = store.addTask('Test Board', {
        title: 'Legacy task',
        column: 'To Do',
        labels: ['backend', 'bug']
      });

      // Should convert labels to tags
      expect(task!.tags).toEqual(['backend', 'bug']);
    });
  });

  describe('Comments and Collaboration', () => {
    it('should add comments to task', () => {
      const task = store.addTask('Test Board', {
        title: 'Task with comments',
        column: 'To Do',
        comments: []
      });

      const comment = {
        id: 'comment-1',
        author: 'developer',
        content: 'Working on this now',
        createdAt: new Date()
      };

      const success = store.updateTask('Test Board', task!.id, {
        comments: [comment]
      });

      expect(success).toBe(true);
      const updatedTask = board.tasks.find(t => t.id === task!.id);
      expect(updatedTask!.comments).toHaveLength(1);
      expect(updatedTask!.comments[0].content).toBe('Working on this now');
    });

    it('should track watchers on task', () => {
      const task = store.addTask('Test Board', {
        title: 'Watched task',
        column: 'To Do',
        watchers: ['user1', 'user2']
      });

      expect(task!.watchers).toEqual(['user1', 'user2']);
    });
  });

  describe('Subtasks', () => {
    it('should add subtasks to main task', () => {
      const task = store.addTask('Test Board', {
        title: 'Main task',
        column: 'To Do',
        subtasks: [
          {
            id: 'subtask-1',
            title: 'Setup environment',
            completed: false
          },
          {
            id: 'subtask-2',
            title: 'Write tests',
            completed: false
          }
        ]
      });

      expect(task!.subtasks).toHaveLength(2);
      expect(task!.subtasks[0].title).toBe('Setup environment');
    });

    it('should update subtask completion', () => {
      const task = store.addTask('Test Board', {
        title: 'Task',
        column: 'To Do',
        subtasks: [{
          id: 'subtask-1',
          title: 'Subtask',
          completed: false
        }]
      });

      const success = store.updateTask('Test Board', task!.id, {
        subtasks: [{
          id: 'subtask-1',
          title: 'Subtask',
          completed: true,
          completedAt: new Date()
        }]
      });

      expect(success).toBe(true);
      const updatedTask = board.tasks.find(t => t.id === task!.id);
      expect(updatedTask!.subtasks[0].completed).toBe(true);
    });
  });

  describe('Attachments', () => {
    it('should add attachments to task', () => {
      const task = store.addTask('Test Board', {
        title: 'Task with files',
        column: 'To Do',
        attachments: [
          {
            id: 'attach-1',
            filename: 'design.pdf',
            url: '/files/design.pdf',
            uploadedBy: 'designer',
            uploadedAt: new Date()
          }
        ]
      });

      expect(task!.attachments).toHaveLength(1);
      expect(task!.attachments[0].filename).toBe('design.pdf');
    });
  });

  describe('Custom Fields', () => {
    it('should support custom fields', () => {
      const task = store.addTask('Test Board', {
        title: 'Task with custom data',
        column: 'To Do',
        customFields: [
          {
            key: 'client',
            value: 'ACME Corp'
          },
          {
            key: 'invoice_number',
            value: 'INV-2024-001'
          }
        ]
      });

      expect(task!.customFields).toHaveLength(2);
      expect(task!.customFields.find(f => f.key === 'client')?.value).toBe('ACME Corp');
    });
  });
});