import { describe, it, expect, vi, beforeEach } from 'vitest'
import { render, screen, fireEvent, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { MemoryRouter } from 'react-router-dom'
import Tasks from '../pages/Tasks'

vi.mock('../api/tasks', () => ({
  tasksApi: {
    list: vi.fn(),
    complete: vi.fn(),
    uncomplete: vi.fn(),
  },
}))

vi.mock('../components/CreateTaskModal', () => ({
  default: ({ open, onClose }) => open ? (
    <div data-testid="create-task-modal">
      <button onClick={onClose}>Close</button>
    </div>
  ) : null,
}))

vi.mock('../components/EditTaskModal', () => ({
  default: ({ open, onClose, task }) => open ? (
    <div data-testid="edit-task-modal">
      <span>{task?.title}</span>
      <button onClick={onClose}>Close</button>
    </div>
  ) : null,
}))

vi.mock('../components/Navigation', () => ({
  default: () => <nav data-testid="navigation">Nav</nav>,
}))

import { tasksApi } from '../api/tasks'

const mockTasks = [
  { id: 1, title: 'Buy groceries', completed: false, priority: 1, due_date: null, icon: '📋', color: '#6366f1', is_recurring: false, recurrence_type: null, description: '' },
  { id: 2, title: 'Read book', completed: false, priority: 2, due_date: '2026-03-30', icon: '📚', color: '#22c55e', is_recurring: false, recurrence_type: null, description: 'Read 30 pages' },
  { id: 3, title: 'Completed task', completed: true, priority: 3, due_date: null, icon: '✅', color: '#f59e0b', is_recurring: true, recurrence_type: 'daily', description: '' },
]

const mockTasksOverdue = [
  { id: 4, title: 'Overdue task', completed: false, priority: 0, due_date: '2020-01-01', icon: '⚠️', color: '#ef4444', is_recurring: false, recurrence_type: null, description: '' },
]

const renderTasks = (embedded = false) => {
  const qc = new QueryClient({ defaultOptions: { queries: { retry: false } } })
  return render(
    <QueryClientProvider client={qc}>
      <MemoryRouter>
        <Tasks embedded={embedded} />
      </MemoryRouter>
    </QueryClientProvider>
  )
}

describe('Tasks page', () => {
  beforeEach(() => {
    vi.clearAllMocks()
    tasksApi.list.mockResolvedValue(mockTasks.filter(t => !t.completed))
  })

  it('renders tasks list', async () => {
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Buy groceries')).toBeInTheDocument()
      expect(screen.getByText('Read book')).toBeInTheDocument()
    })
  })

  it('renders header when not embedded', async () => {
    renderTasks(false)
    await waitFor(() => {
      expect(screen.getByText('Задачи')).toBeInTheDocument()
    })
  })

  it('does not render header when embedded', async () => {
    renderTasks(true)
    await waitFor(() => {
      expect(screen.queryByText('Задачи')).not.toBeInTheDocument()
    })
  })

  it('renders filter buttons', async () => {
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Активные')).toBeInTheDocument()
      expect(screen.getByText('Выполненные')).toBeInTheDocument()
      expect(screen.getByText('Все')).toBeInTheDocument()
    })
  })

  it('renders navigation when not embedded', () => {
    renderTasks(false)
    expect(screen.getByTestId('navigation')).toBeInTheDocument()
  })

  it('does not render navigation when embedded', () => {
    renderTasks(true)
    expect(screen.queryByTestId('navigation')).not.toBeInTheDocument()
  })

  it('shows empty state when no tasks', async () => {
    tasksApi.list.mockResolvedValue([])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText(/Нет активных задач/)).toBeInTheDocument()
    })
  })

  it('shows add task button in empty state for active filter', async () => {
    tasksApi.list.mockResolvedValue([])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Добавить задачу')).toBeInTheDocument()
    })
  })

  it('opens create task modal', async () => {
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Задачи')).toBeInTheDocument()
    })
    const plusBtn = document.querySelector('button.bg-primary-500') || document.querySelector('button[class*="bg-primary"]')
    if (plusBtn) {
      fireEvent.click(plusBtn)
      expect(screen.getByTestId('create-task-modal')).toBeInTheDocument()
    }
  })

  it('opens add task modal from empty state button', async () => {
    tasksApi.list.mockResolvedValue([])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Добавить задачу')).toBeInTheDocument()
    })
    fireEvent.click(screen.getByText('Добавить задачу'))
    expect(screen.getByTestId('create-task-modal')).toBeInTheDocument()
  })

  it('switches to completed filter', async () => {
    tasksApi.list.mockResolvedValue([mockTasks[2]])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Выполненные')).toBeInTheDocument()
    })
    fireEvent.click(screen.getByText('Выполненные'))
    await waitFor(() => {
      expect(tasksApi.list).toHaveBeenCalledWith(true)
    })
  })

  it('switches to all filter', async () => {
    tasksApi.list.mockResolvedValue(mockTasks)
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Все')).toBeInTheDocument()
    })
    fireEvent.click(screen.getByText('Все'))
    await waitFor(() => {
      expect(tasksApi.list).toHaveBeenCalled()
    })
  })

  it('completes a task on click', async () => {
    tasksApi.complete.mockResolvedValue({ id: 1, completed: true })
    tasksApi.list.mockResolvedValue([mockTasks[0]])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Buy groceries')).toBeInTheDocument()
    })
    // Get all buttons: [0]=create(+), [1]=complete-task-btn, [2]=edit-btn
    const allBtns = screen.getAllByRole('button')
    if (allBtns.length > 1) {
      fireEvent.click(allBtns[4])
      await waitFor(() => {
        expect(tasksApi.complete).toHaveBeenCalledWith(1)
      }, { timeout: 3000 })
    }
  })

  it('shows priority badge for tasks', async () => {
    tasksApi.list.mockResolvedValue([mockTasks[1]])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Read book')).toBeInTheDocument()
    })
    expect(screen.getByText('Средний')).toBeInTheDocument()
  })

  it('shows high priority badge', async () => {
    tasksApi.list.mockResolvedValue([mockTasks[2]])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Completed task')).toBeInTheDocument()
    })
    expect(screen.getByText('Высокий')).toBeInTheDocument()
  })

  it('shows due date for tasks', async () => {
    tasksApi.list.mockResolvedValue([mockTasks[1]])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Read book')).toBeInTheDocument()
    })
    expect(document.querySelector('[class*="text-gray"]')).toBeTruthy()
  })

  it('shows overdue indicator', async () => {
    tasksApi.list.mockResolvedValue(mockTasksOverdue)
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Overdue task')).toBeInTheDocument()
    })
    expect(document.querySelector('svg')).toBeTruthy()
  })

  it('opens edit modal when task title clicked', async () => {
    tasksApi.list.mockResolvedValue([mockTasks[0]])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Buy groceries')).toBeInTheDocument()
    })
    fireEvent.click(screen.getByText('Buy groceries'))
    await waitFor(() => {
      expect(screen.getByTestId('edit-task-modal')).toBeInTheDocument()
    })
  })

  it('closes edit modal', async () => {
    tasksApi.list.mockResolvedValue([mockTasks[0]])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Buy groceries')).toBeInTheDocument()
    })
    fireEvent.click(screen.getByText('Buy groceries'))
    await waitFor(() => {
      expect(screen.getByTestId('edit-task-modal')).toBeInTheDocument()
    })
    fireEvent.click(screen.getByText('Close'))
    expect(screen.queryByTestId('edit-task-modal')).not.toBeInTheDocument()
  })

  it('shows recurring icon for recurring tasks', async () => {
    tasksApi.list.mockResolvedValue([mockTasks[2]])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Completed task')).toBeInTheDocument()
    })
    expect(screen.getByText('🔄')).toBeInTheDocument()
  })

  it('shows recurrence label', async () => {
    tasksApi.list.mockResolvedValue([mockTasks[2]])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Ежедневно')).toBeInTheDocument()
    })
  })

  it('shows task description', async () => {
    tasksApi.list.mockResolvedValue([mockTasks[1]])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Read 30 pages')).toBeInTheDocument()
    })
  })

  it('uncompletes a task', async () => {
    tasksApi.uncomplete.mockResolvedValue({ id: 3, completed: false })
    const completedTask = { ...mockTasks[2], completed: true }
    tasksApi.list.mockResolvedValue([completedTask])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Completed task')).toBeInTheDocument()
    })
    const undoBtn = document.querySelector('[title="Отменить"]')
    if (undoBtn) {
      fireEvent.click(undoBtn)
      await waitFor(() => {
        expect(tasksApi.uncomplete).toHaveBeenCalledWith(3)
      })
    }
  })

  it('shows empty state for completed filter', async () => {
    tasksApi.list.mockResolvedValue([])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Выполненные')).toBeInTheDocument()
    })
    fireEvent.click(screen.getByText('Выполненные'))
    await waitFor(() => {
      expect(screen.getByText(/Нет выполненных задач/)).toBeInTheDocument()
    })
  })

  it('shows empty state for all filter', async () => {
    tasksApi.list.mockResolvedValue([])
    renderTasks()
    await waitFor(() => {
      expect(screen.getByText('Все')).toBeInTheDocument()
    })
    fireEvent.click(screen.getByText('Все'))
    await waitFor(() => {
      expect(screen.getByText(/Нет задач/)).toBeInTheDocument()
    })
  })
})
