import React from 'react';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { ThemeProvider } from 'styled-components';
import { MemoryRouter } from 'react-router-dom';
import { I18nextProvider } from 'react-i18next';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import '@testing-library/jest-dom';
import ProjectsPage from '@/features/projects/pages/ProjectsPage';
import * as projectService from '@/features/projects/services/projectService';
import type { PaginatedResponse } from '@/shared/types/pagination.types';
import type { ProjectSummary } from '@/features/projects/types/project.types';
import i18n from '@/locales/i18n';
import { LocaleProvider } from '@/app/providers/LocaleProvider';
import { lightTheme } from '@/styles/theme';

vi.mock('@/features/projects/services/projectService');
vi.mock('@/shared/components/layout/AppLayout', () => ({
  AppLayout: ({ children }: { children: React.ReactNode }) => <div>{children}</div>,
}));

const mockProject: ProjectSummary = {
  id: 'p1',
  company_id: 'c1',
  department_id: 'd1',
  department: { id: 'd1', name: 'Support', code: 'SUP' },
  owner_user_id: 'u1',
  owner: { id: 'u1', name: 'Head', email: 'head@test.com' },
  name: 'Alpha',
  key: 'ALPHA',
  description: null,
  status: 'active',
  start_date: null,
  due_date: '2026-12-31',
  completed_at: null,
  color: null,
  completion_percentage: 40,
  health_level: 'healthy',
  is_overdue: false,
  created_at: '2026-01-01',
  updated_at: '2026-01-02',
};

const paginated: PaginatedResponse<ProjectSummary> = {
  data: [mockProject],
  meta: { current_page: 1, last_page: 1, per_page: 24, total: 1 },
};

const emptyPaginated: PaginatedResponse<ProjectSummary> = {
  data: [],
  meta: { current_page: 1, last_page: 1, per_page: 24, total: 0 },
};

function renderPage() {
  const queryClient = new QueryClient({ defaultOptions: { queries: { retry: false } } });
  return render(
    <QueryClientProvider client={queryClient}>
      <I18nextProvider i18n={i18n}>
        <LocaleProvider>
          <ThemeProvider theme={lightTheme}>
            <MemoryRouter>
              <ProjectsPage />
            </MemoryRouter>
          </ThemeProvider>
        </LocaleProvider>
      </I18nextProvider>
    </QueryClientProvider>,
  );
}

describe('ProjectsPage', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    void i18n.changeLanguage('en');
  });

  it('shows loading skeleton while fetching', () => {
    vi.mocked(projectService.fetchProjects).mockReturnValue(new Promise(() => {}));

    renderPage();

    expect(screen.getByRole('status', { name: /loading projects/i })).toBeInTheDocument();
  });

  it('renders project cards on success', async () => {
    vi.mocked(projectService.fetchProjects).mockResolvedValue(paginated);

    renderPage();

    await waitFor(() => expect(screen.getByText('Alpha')).toBeInTheDocument());
    expect(screen.getByTestId('projects-grid')).toBeInTheDocument();
  });

  it('shows empty state when there are no projects', async () => {
    vi.mocked(projectService.fetchProjects).mockResolvedValue(emptyPaginated);

    renderPage();

    await waitFor(() => {
      expect(screen.getByText('No Projects Yet')).toBeInTheDocument();
    });
    expect(
      screen.getByText(/organize backlog items, sprints, milestones, and work items/i),
    ).toBeInTheDocument();
  });

  it('shows error state with retry when fetch fails', async () => {
    vi.mocked(projectService.fetchProjects).mockRejectedValue(new Error('Server error'));

    renderPage();

    await waitFor(() => expect(screen.getByRole('alert')).toBeInTheDocument());
    expect(screen.getByText('Server error')).toBeInTheDocument();
    expect(screen.getByRole('button', { name: /try again/i })).toBeInTheDocument();
  });

  it('shows forbidden state on 403', async () => {
    vi.mocked(projectService.fetchProjects).mockRejectedValue({
      response: { status: 403, data: { message: 'Forbidden' } },
    });

    renderPage();

    await waitFor(() => {
      expect(screen.getByText(/do not have permission to view projects/i)).toBeInTheDocument();
    });
  });

  it('opens create project modal from header button', async () => {
    vi.mocked(projectService.fetchProjects).mockResolvedValue(emptyPaginated);

    renderPage();

    await waitFor(() => expect(screen.getByText('No Projects Yet')).toBeInTheDocument());

    fireEvent.click(screen.getByTestId('projects-create-button'));

    expect(screen.getByTestId('create-project-modal')).toBeInTheDocument();
  });
});
