
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { TaskDrawer } from '../TaskDrawer';
import type { Task, User } from '../data';

// Mock Shared components to avoid testing their specific implementation here
vi.mock('../Shared', () => ({
    Avatar: ({ userId }: any) => <div data-testid="avatar">{userId}</div>,
    Tag: ({ label }: any) => <div>{label}</div>,
    ProgressBar: () => <div>Progress</div>
}));

describe('TaskDrawer Component', () => {
    const mockUser: User = { id: 'u1', name: 'Test User', email: 'test@example.com', role: 'emp', dept: 'dev', avatar: 'TU', color: '#000' };
    const mockUsers = [mockUser, { id: 'u2', name: 'Other User', email: 'other@example.com', role: 'emp', dept: 'dev', avatar: 'OU', color: '#fff' }];

    const mockTask: Task = {
        id: 't1',
        title: 'Test Task',
        description: 'Test Description',
        status: 'todo',
        priority: 'medium',
        assignee: 'u1',
        reporter: 'u1',
        dueDate: '2023-12-31',
        tags: ['bug'],
        subtasks: [],
        comments: [],
        activity: [],
        dependencies: []
    };

    const mockOnUpdate = vi.fn();
    const mockOnClose = vi.fn();
    const mockOnAddDep = vi.fn();
    const mockOnToggleDep = vi.fn();
    const mockOnRemoveDep = vi.fn();

    beforeEach(() => {
        vi.clearAllMocks();
    });

    it('renders task details correctly', () => {
        render(<TaskDrawer task={mockTask} currentUser={mockUser} onClose={mockOnClose} onUpdate={mockOnUpdate} onAddDependency={mockOnAddDep} onToggleDependency={mockOnToggleDep} onRemoveDependency={mockOnRemoveDep} users={mockUsers} />);

        // screen.debug();

        expect(screen.getByText('Test Task')).toBeInTheDocument();
        expect(screen.getByText('Test Description')).toBeInTheDocument();
        // Check for mocked avatar with userId
        const avatars = screen.getAllByTestId('avatar');
        expect(avatars.length).toBeGreaterThan(0);
        expect(avatars[0]).toHaveTextContent('u1');
        // expect(screen.getByText(/Test User/i)).toBeInTheDocument(); // Assignee name might be tricky in Select/Div 
        expect(screen.getByText('bug')).toBeInTheDocument();
    });

    it('updates title/description calling onUpdate', async () => {
        // Title isn't editable in the drawer based on code, only via modal or just display? 
        // Checking code: <h2 className="drawer-title">{task.title}</h2>. It's not an input.
        // But status, priority, assignee are selects.

        render(<TaskDrawer task={mockTask} currentUser={mockUser} onClose={mockOnClose} onUpdate={mockOnUpdate} onAddDependency={mockOnAddDep} onToggleDependency={mockOnToggleDep} onRemoveDependency={mockOnRemoveDep} users={mockUsers} />);

        // Update status
        const statusSelect = screen.getByRole('combobox', { name: /status/i });
        await userEvent.selectOptions(statusSelect, 'done');

        expect(mockOnUpdate).toHaveBeenCalledWith(expect.objectContaining({
            id: 't1',
            status: 'done'
        }));
    });

    it('adds a subtask', async () => {
        render(<TaskDrawer task={mockTask} currentUser={mockUser} onClose={mockOnClose} onUpdate={mockOnUpdate} onAddDependency={mockOnAddDep} onToggleDependency={mockOnToggleDep} onRemoveDependency={mockOnRemoveDep} users={mockUsers} />);

        const input = screen.getByPlaceholderText(/add a subtask/i);
        await userEvent.type(input, 'New Subtask{enter}');

        expect(mockOnUpdate).toHaveBeenCalledWith(expect.objectContaining({
            subtasks: expect.arrayContaining([expect.objectContaining({ title: 'New Subtask', done: false })])
        }));
    });

    it('adds a comment', async () => {
        render(<TaskDrawer task={mockTask} currentUser={mockUser} onClose={mockOnClose} onUpdate={mockOnUpdate} onAddDependency={mockOnAddDep} onToggleDependency={mockOnToggleDep} onRemoveDependency={mockOnRemoveDep} users={mockUsers} />);

        const input = screen.getByPlaceholderText(/add a comment/i);
        await userEvent.type(input, 'This is a comment{enter}');

        expect(mockOnUpdate).toHaveBeenCalledWith(expect.objectContaining({
            comments: expect.arrayContaining([expect.objectContaining({ text: 'This is a comment', userId: 'u1' })])
        }));
    });

    it('adds a dependency', async () => {
        render(<TaskDrawer task={mockTask} currentUser={mockUser} onClose={mockOnClose} onUpdate={mockOnUpdate} onAddDependency={mockOnAddDep} onToggleDependency={mockOnToggleDep} onRemoveDependency={mockOnRemoveDep} users={mockUsers} />);

        const descInput = screen.getByPlaceholderText(/describe the dependency/i);
        await userEvent.type(descInput, 'Blocked by API{enter}');

        // Default select is "Anyone" (empty string). 
        expect(mockOnAddDep).toHaveBeenCalledWith('t1', { dependsOnUserId: '', description: 'Blocked by API' });
    });
});
