import { render, screen, act } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import TaskDetailPage from '@/app/(protected)/tasks/[id]/page';
import { useTask, useUpdateTask, useAssignTask, useUnassignTask } from '@/hooks/useTasks';

vi.mock('next/navigation', () => ({
  useRouter: vi.fn(() => ({
    push: vi.fn(),
    replace: vi.fn(),
    back: vi.fn(),
  })),
}));

vi.mock('next-auth/react', () => ({
  useSession: vi.fn(() => ({
    data: { user: { id: 'user-123' } },
    status: 'authenticated',
  })),
}));

vi.mock('@/hooks/useTasks', () => ({
  useTask: vi.fn(),
  useUpdateTask: vi.fn(),
  useAssignTask: vi.fn(),
  useUnassignTask: vi.fn(),
}));

describe('TaskDetailPage', () => {
  const mockUpdate = vi.fn();
  const mockAssign = vi.fn();
  const mockUnassign = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
    (useUpdateTask as ReturnType<typeof vi.fn>).mockReturnValue({
      mutate: mockUpdate,
      isPending: false,
    });
    (useAssignTask as ReturnType<typeof vi.fn>).mockReturnValue({
      mutate: mockAssign,
      isPending: false,
    });
    (useUnassignTask as ReturnType<typeof vi.fn>).mockReturnValue({
      mutate: mockUnassign,
      isPending: false,
    });
  });

  it('shows valid transitions for Open status', async () => {
    (useTask as ReturnType<typeof vi.fn>).mockReturnValue({
      data: { id: '1', title: 'Task 1', status: 'Open', description: 'Desc', createdAt: '2024-01-01', updatedAt: '2024-01-01', isAssignedToMe: false },
      isLoading: false,
      error: null,
    });

    const params = Promise.resolve({ id: '1' });
    await act(async () => {
      render(<TaskDetailPage params={params} />);
    });
    
    expect(screen.getByText('Move to Assigned')).toBeInTheDocument();
    expect(screen.queryByText('Move to InProgress')).not.toBeInTheDocument();
    expect(screen.queryByText('Mark as Done')).not.toBeInTheDocument();
  });

  it('shows valid transitions for InProgress status', async () => {
    (useTask as ReturnType<typeof vi.fn>).mockReturnValue({
      data: { id: '1', title: 'Task 1', status: 'InProgress', description: 'Desc', createdAt: '2024-01-01', updatedAt: '2024-01-01', isAssignedToMe: false },
      isLoading: false,
      error: null,
    });

    const params = Promise.resolve({ id: '1' });
    await act(async () => {
      render(<TaskDetailPage params={params} />);
    });
    
    expect(screen.getByText('Move to Review')).toBeInTheDocument();
    expect(screen.queryByText('Mark as Done')).not.toBeInTheDocument();
  });

  it('shows valid transitions for Review status (including back transition)', async () => {
    (useTask as ReturnType<typeof vi.fn>).mockReturnValue({
      data: { id: '1', title: 'Task 1', status: 'Review', description: 'Desc', createdAt: '2024-01-01', updatedAt: '2024-01-01', isAssignedToMe: false },
      isLoading: false,
      error: null,
    });

    const params = Promise.resolve({ id: '1' });
    await act(async () => {
      render(<TaskDetailPage params={params} />);
    });
    
    expect(screen.getByText('Mark as Done')).toBeInTheDocument();
    expect(screen.getByText('Back to InProgress')).toBeInTheDocument();
  });

  it('renders Assign to Me button when task unassigned and session exists', async () => {
    (useTask as ReturnType<typeof vi.fn>).mockReturnValue({
      data: { 
        id: '1', 
        title: 'Task 1', 
        status: 'Open', 
        assigneeId: null,
        description: 'Desc', 
        createdAt: '2024-01-01', 
        updatedAt: '2024-01-01',
        isAssignedToMe: false
      },
      isLoading: false,
      error: null,
    });

    const params = Promise.resolve({ id: '1' });
    await act(async () => {
      render(<TaskDetailPage params={params} />);
    });
    
    expect(screen.getByText('Assign to Me')).toBeInTheDocument();
  });

  it('calls assignTask with task id when Assign to Me clicked', async () => {
    (useTask as ReturnType<typeof vi.fn>).mockReturnValue({
      data: { 
        id: '1', 
        title: 'Task 1', 
        status: 'Open', 
        assigneeId: null,
        description: 'Desc', 
        createdAt: '2024-01-01', 
        updatedAt: '2024-01-01',
        isAssignedToMe: false
      },
      isLoading: false,
      error: null,
    });

    const params = Promise.resolve({ id: '1' });
    await act(async () => {
      render(<TaskDetailPage params={params} />);
    });

    const button = screen.getByText('Assign to Me');
    await act(async () => {
      button.click();
    });

    expect(mockAssign).toHaveBeenCalledWith('1');
  });

  it('renders Unassign button and calls unassignTask when clicked', async () => {
    (useTask as ReturnType<typeof vi.fn>).mockReturnValue({
      data: { 
        id: '1', 
        title: 'Task 1', 
        status: 'Assigned', 
        assigneeId: 'some-member-id',
        description: 'Desc', 
        createdAt: '2024-01-01', 
        updatedAt: '2024-01-01',
        isAssignedToMe: true
      },
      isLoading: false,
      error: null,
    });

    const params = Promise.resolve({ id: '1' });
    await act(async () => {
      render(<TaskDetailPage params={params} />);
    });

    const button = screen.getByText('Unassign');
    expect(button).toBeInTheDocument();
    
    await act(async () => {
      button.click();
    });

    expect(mockUnassign).toHaveBeenCalledWith('1');
  });
});
