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, Route, Routes } from 'react-router-dom';
import { I18nextProvider } from 'react-i18next';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import '@testing-library/jest-dom';
import TicketDetailPage from '@/features/tickets/pages/TicketDetailPage';
import * as ticketService from '@/features/tickets/services/ticketService';
import type { TicketDetail, TicketReply } from '@/features/tickets/types/ticket.types';
import type { PaginatedResponse } from '@/shared/types/pagination.types';
import i18n from '@/locales/i18n';
import { LocaleProvider } from '@/app/providers/LocaleProvider';
import { lightTheme } from '@/styles/theme';

vi.mock('@/features/tickets/services/ticketService');
vi.mock('@/features/tickets/services/slaService', () => ({
  fetchTicketSla: vi.fn().mockResolvedValue(null),
}));
vi.mock('@/features/tickets/services/departmentSupportService', () => ({
  fetchDepartmentAssignableUsers: vi.fn().mockResolvedValue([]),
  fetchTicketFormOptions: vi.fn().mockResolvedValue({
    categories: [],
    statuses: [
      {
        id: 'st-1',
        name_en: 'Open',
        name_ar: 'مفتوح',
        color: '#f00',
        is_closed: false,
        sort_order: 1,
      },
    ],
    priorities: [
      {
        id: 'pr-1',
        name_en: 'Normal',
        name_ar: 'عادي',
        color: '#0f0',
        sort_order: 2,
      },
    ],
  }),
}));

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

const mockTicket: TicketDetail = {
  id: 'ticket-1',
  ticket_number: 'TKT-100',
  subject: 'Printer jam',
  description: 'Paper stuck',
  department: { id: 'dept-1', name: 'IT', code: 'IT' },
  requester: { id: 'u1', name: 'Jane', email: 'jane@test.com' },
  assignee: null,
  status: {
    id: 'st-1',
    name_en: 'Open',
    name_ar: 'مفتوح',
    color: '#f00',
    is_closed: false,
  },
  priority: {
    id: 'pr-1',
    name_en: 'Normal',
    name_ar: 'عادي',
    color: '#0f0',
    sort_order: 2,
  },
  first_response_at: null,
  resolved_at: null,
  closed_at: null,
  created_at: '2026-05-18T10:00:00Z',
  updated_at: '2026-05-18T12:00:00Z',
  age_in_days: 1,
  is_assigned: false,
  is_open: true,
  time_to_first_response_minutes: null,
  time_to_resolution_minutes: null,
  status_history: [],
};

const mockReply: TicketReply = {
  id: 'reply-1',
  ticket_id: 'ticket-1',
  user: { id: 'u2', name: 'Agent', email: 'agent@test.com' },
  content: 'We are investigating.',
  is_solution: false,
  created_at: '2026-05-18T11:00:00Z',
  updated_at: '2026-05-18T11:00:00Z',
};

function renderTicketDetail() {
  const queryClient = new QueryClient({
    defaultOptions: { queries: { retry: false } },
  });

  return render(
    <QueryClientProvider client={queryClient}>
      <I18nextProvider i18n={i18n}>
        <LocaleProvider>
          <ThemeProvider theme={lightTheme}>
            <MemoryRouter initialEntries={['/tickets/ticket-1']}>
              <Routes>
                <Route path="/tickets/:id" element={<TicketDetailPage />} />
              </Routes>
            </MemoryRouter>
          </ThemeProvider>
        </LocaleProvider>
      </I18nextProvider>
    </QueryClientProvider>,
  );
}

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

    vi.mocked(ticketService.fetchTickets).mockResolvedValue({
      data: [mockTicket],
      meta: { current_page: 1, last_page: 1, per_page: 100, total: 1 },
    } satisfies PaginatedResponse<typeof mockTicket>);

    vi.mocked(ticketService.fetchTicketReplies).mockResolvedValue([]);
    vi.mocked(ticketService.fetchTicketNotes).mockResolvedValue([]);
  });

  it('renders ticket detail', async () => {
    vi.mocked(ticketService.fetchTicket).mockResolvedValue(mockTicket);

    renderTicketDetail();

    await waitFor(() => {
      expect(screen.getByText('Printer jam')).toBeInTheDocument();
    });

    expect(screen.getByText('Paper stuck')).toBeInTheDocument();
    expect(screen.getAllByText(/TKT-100/).length).toBeGreaterThan(0);
  });

  it('submits reply successfully', async () => {
    vi.mocked(ticketService.fetchTicket).mockResolvedValue(mockTicket);
    vi.mocked(ticketService.createTicketReply).mockResolvedValue(mockReply);

    renderTicketDetail();

    await waitFor(() => {
      expect(screen.getByText('Printer jam')).toBeInTheDocument();
    });

    const textarea = screen.getByPlaceholderText(/type your reply/i);
    fireEvent.change(textarea, { target: { value: 'Customer updated.' } });

    const submitButtons = screen.getAllByRole('button', { name: /^submit$/i });
    fireEvent.click(submitButtons[0]);

    await waitFor(() => {
      expect(ticketService.createTicketReply).toHaveBeenCalledWith(
        'ticket-1',
        'Customer updated.',
        [],
      );
    });
  });
});
