/**
 * Unit tests for CustomerSupport component
 *
 * Tests support ticket functionality including:
 * - Ticket list display
 * - Ticket creation
 * - Ticket detail view
 * - Comments/conversation
 * - Status badges
 * - Loading and error states
 */

import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import React from 'react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { MemoryRouter, Outlet, Routes, Route } from 'react-router-dom';
import CustomerSupport from '../CustomerSupport';

// Mock react-i18next
vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string, fallback?: string, options?: any) => {
      if (options?.number !== undefined) {
        return fallback?.replace('{{number}}', options.number) || key;
      }
      if (options?.date !== undefined) {
        return fallback?.replace('{{date}}', options.date) || key;
      }
      return fallback || key;
    },
  }),
}));

// Mock the ticket hooks
const mockTickets = vi.fn();
const mockCreateTicket = vi.fn();
const mockTicketComments = vi.fn();
const mockCreateTicketComment = vi.fn();

vi.mock('../../../hooks/useTickets', () => ({
  useTickets: () => mockTickets(),
  useCreateTicket: () => ({
    mutateAsync: mockCreateTicket,
    isPending: false,
  }),
  useTicketComments: (ticketId: string) => mockTicketComments(ticketId),
  useCreateTicketComment: () => ({
    mutateAsync: mockCreateTicketComment,
    isPending: false,
  }),
}));

const mockUser = {
  id: 'user-1',
  email: 'customer@example.com',
  name: 'John Doe',
  role: 'customer' as const,
};

const mockBusiness = {
  id: 'biz-1',
  name: 'Test Business',
  subdomain: 'test',
  cancellationWindowHours: 24,
  lateCancellationFeePercent: 50,
};

const defaultTickets = [
  {
    id: '1',
    ticketNumber: 'TKT-001',
    ticketType: 'CUSTOMER',
    subject: 'Appointment rescheduling',
    description: 'I need to reschedule my appointment',
    status: 'OPEN',
    priority: 'MEDIUM',
    category: 'APPOINTMENT',
    createdAt: '2024-12-01T10:00:00Z',
    updatedAt: '2024-12-01T10:00:00Z',
    creatorEmail: 'customer@example.com',
    creatorFullName: 'John Doe',
  },
  {
    id: '2',
    ticketNumber: 'TKT-002',
    ticketType: 'CUSTOMER',
    subject: 'Refund request',
    description: 'I would like a refund for my last appointment',
    status: 'RESOLVED',
    priority: 'HIGH',
    category: 'REFUND',
    createdAt: '2024-11-20T14:00:00Z',
    updatedAt: '2024-11-22T16:00:00Z',
    resolvedAt: '2024-11-22T16:00:00Z',
    creatorEmail: 'customer@example.com',
    creatorFullName: 'John Doe',
  },
  {
    id: '3',
    ticketNumber: 'TKT-003',
    ticketType: 'PLATFORM',
    subject: 'Platform issue',
    description: 'This should be filtered out',
    status: 'OPEN',
    priority: 'LOW',
    category: 'OTHER',
    createdAt: '2024-11-15T09:00:00Z',
    updatedAt: '2024-11-15T09:00:00Z',
    creatorEmail: 'platform@example.com',
    creatorFullName: 'Platform User',
  },
];

const defaultComments = [
  {
    id: '1',
    ticket: '1',
    author: 'staff-1',
    authorEmail: 'staff@example.com',
    authorFullName: 'Support Staff',
    commentText: 'We have received your request and are looking into it.',
    isInternal: false,
    createdAt: '2024-12-01T11:00:00Z',
  },
  {
    id: '2',
    ticket: '1',
    author: 'staff-2',
    authorEmail: 'manager@example.com',
    authorFullName: 'Manager',
    commentText: 'Internal note: escalate this',
    isInternal: true,
    createdAt: '2024-12-01T12:00:00Z',
  },
  {
    id: '3',
    ticket: '1',
    author: 'user-1',
    authorEmail: 'customer@example.com',
    authorFullName: 'John Doe',
    commentText: 'Thank you for your help!',
    isInternal: false,
    createdAt: '2024-12-01T13:00:00Z',
  },
];

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

  const OutletWrapper = () => {
    return React.createElement(Outlet, {
      context: { user: mockUser, business: mockBusiness },
    });
  };

  return ({ children }: { children: React.ReactNode }) =>
    React.createElement(
      QueryClientProvider,
      { client: queryClient },
      React.createElement(
        MemoryRouter,
        { initialEntries: ['/customer/support'] },
        React.createElement(
          Routes,
          null,
          React.createElement(Route, {
            element: React.createElement(OutletWrapper),
            children: React.createElement(Route, {
              path: 'customer/support',
              element: children,
            }),
          })
        )
      )
    );
};

describe('CustomerSupport', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    mockTickets.mockReturnValue({
      data: defaultTickets,
      isLoading: false,
      refetch: vi.fn(),
    });
    mockTicketComments.mockReturnValue({
      data: [],
      isLoading: false,
    });
  });

  describe('Page Header', () => {
    it('should render the page title', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText('Support')).toBeInTheDocument();
    });

    it('should render the page subtitle', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText(/Get help with your appointments and account/)).toBeInTheDocument();
    });

    it('should render New Request button', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText('New Request')).toBeInTheDocument();
    });
  });

  describe('Quick Help Section', () => {
    it('should render Quick Help heading', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText('Quick Help')).toBeInTheDocument();
    });

    it('should render Contact Us option', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText('Contact Us')).toBeInTheDocument();
      expect(screen.getByText('Submit a support request')).toBeInTheDocument();
    });

    it('should render Email Us option', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText('Email Us')).toBeInTheDocument();
      expect(screen.getByText('Get help via email')).toBeInTheDocument();
    });

    it('should have email link with business subdomain', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const emailLink = screen.getByText('Email Us').closest('a');
      expect(emailLink).toHaveAttribute('href', 'mailto:support@test.smoothschedule.com');
    });

    it('should open new ticket form when Contact Us is clicked', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const contactButton = screen.getAllByText('Contact Us')[0].closest('a');
      fireEvent.click(contactButton!);

      expect(screen.getByText('Submit a Support Request')).toBeInTheDocument();
    });
  });

  describe('My Support Requests Section', () => {
    it('should render section heading', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText('My Support Requests')).toBeInTheDocument();
    });

    it('should display customer tickets only', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText('Appointment rescheduling')).toBeInTheDocument();
      expect(screen.getByText('Refund request')).toBeInTheDocument();
      expect(screen.queryByText('Platform issue')).not.toBeInTheDocument();
    });

    it('should display ticket numbers', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText(/TKT-001/)).toBeInTheDocument();
      expect(screen.getByText(/TKT-002/)).toBeInTheDocument();
    });

    it('should display ticket status badges', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText(/open/i)).toBeInTheDocument();
      expect(screen.getByText(/resolved/i)).toBeInTheDocument();
    });

    it('should display ticket creation dates', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const dateElements = screen.getAllByText(/12\/1\/2024|11\/20\/2024/);
      expect(dateElements.length).toBeGreaterThan(0);
    });

    it('should render loading state', () => {
      mockTickets.mockReturnValue({
        data: [],
        isLoading: true,
        refetch: vi.fn(),
      });
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText('Loading...')).toBeInTheDocument();
    });

    it('should render empty state when no tickets', () => {
      mockTickets.mockReturnValue({
        data: [],
        isLoading: false,
        refetch: vi.fn(),
      });
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText(/haven't submitted any support requests yet/)).toBeInTheDocument();
    });

    it('should show Submit first request button in empty state', () => {
      mockTickets.mockReturnValue({
        data: [],
        isLoading: false,
        refetch: vi.fn(),
      });
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      expect(screen.getByText('Submit your first request')).toBeInTheDocument();
    });

    it('should open ticket detail when ticket is clicked', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const ticketButton = screen.getByText('Appointment rescheduling').closest('button');
      fireEvent.click(ticketButton!);

      expect(screen.getByText('Appointment Details')).toBeInTheDocument();
    });
  });

  describe('New Ticket Form Modal', () => {
    beforeEach(() => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const newRequestButton = screen.getAllByText('New Request')[0];
      fireEvent.click(newRequestButton);
    });

    it('should render form modal when New Request is clicked', () => {
      expect(screen.getByText('Submit a Support Request')).toBeInTheDocument();
    });

    it('should render subject input field', () => {
      expect(screen.getByLabelText(/subject/i)).toBeInTheDocument();
    });

    it('should render category dropdown', () => {
      expect(screen.getByLabelText(/category/i)).toBeInTheDocument();
    });

    it('should render priority dropdown', () => {
      expect(screen.getByLabelText(/priority/i)).toBeInTheDocument();
    });

    it('should render description textarea', () => {
      expect(screen.getByLabelText(/description/i)).toBeInTheDocument();
    });

    it('should render Cancel button', () => {
      expect(screen.getByText('Cancel')).toBeInTheDocument();
    });

    it('should render Submit Request button', () => {
      expect(screen.getByText('Submit Request')).toBeInTheDocument();
    });

    it('should close modal when Cancel is clicked', () => {
      const cancelButton = screen.getByText('Cancel');
      fireEvent.click(cancelButton);

      expect(screen.queryByText('Submit a Support Request')).not.toBeInTheDocument();
    });

    it('should close modal when clicking outside', () => {
      const backdrop = screen.getByText('Submit a Support Request').closest('.fixed');
      fireEvent.click(backdrop!);

      expect(screen.queryByText('Submit a Support Request')).not.toBeInTheDocument();
    });

    it('should not close modal when clicking inside form', () => {
      const formContent = screen.getByLabelText(/subject/i).closest('.bg-white');
      fireEvent.click(formContent!);

      expect(screen.getByText('Submit a Support Request')).toBeInTheDocument();
    });

    it('should submit form with correct data', async () => {
      const subjectInput = screen.getByLabelText(/subject/i);
      const descriptionInput = screen.getByLabelText(/description/i);
      const submitButton = screen.getByText('Submit Request');

      fireEvent.change(subjectInput, { target: { value: 'Test ticket' } });
      fireEvent.change(descriptionInput, { target: { value: 'Test description' } });
      fireEvent.click(submitButton);

      await waitFor(() => {
        expect(mockCreateTicket).toHaveBeenCalledWith({
          subject: 'Test ticket',
          description: 'Test description',
          category: 'GENERAL_INQUIRY',
          priority: 'MEDIUM',
          ticketType: 'CUSTOMER',
        });
      });
    });

    it('should display category options', () => {
      const categorySelect = screen.getByLabelText(/category/i);
      expect(categorySelect).toBeInTheDocument();
      // Options are rendered as part of select
      expect(screen.getByText(/appointment/i)).toBeInTheDocument();
    });

    it('should display priority options', () => {
      const prioritySelect = screen.getByLabelText(/priority/i);
      expect(prioritySelect).toBeInTheDocument();
      expect(screen.getByText(/medium/i)).toBeInTheDocument();
    });

    it('should require subject field', () => {
      const subjectInput = screen.getByLabelText(/subject/i) as HTMLInputElement;
      expect(subjectInput.required).toBe(true);
    });

    it('should require description field', () => {
      const descriptionInput = screen.getByLabelText(/description/i) as HTMLTextAreaElement;
      expect(descriptionInput.required).toBe(true);
    });
  });

  describe('Ticket Detail View', () => {
    beforeEach(() => {
      mockTicketComments.mockReturnValue({
        data: defaultComments,
        isLoading: false,
      });
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const ticketButton = screen.getByText('Appointment rescheduling').closest('button');
      fireEvent.click(ticketButton!);
    });

    it('should display ticket subject', () => {
      expect(screen.getByText('Appointment rescheduling')).toBeInTheDocument();
    });

    it('should display ticket number', () => {
      expect(screen.getByText(/Ticket #TKT-001/)).toBeInTheDocument();
    });

    it('should display creation date', () => {
      expect(screen.getByText(/Created.*12\/1\/2024/)).toBeInTheDocument();
    });

    it('should display status badge', () => {
      expect(screen.getByText(/open/i)).toBeInTheDocument();
    });

    it('should display priority badge', () => {
      expect(screen.getByText(/medium/i)).toBeInTheDocument();
    });

    it('should display ticket description', () => {
      expect(screen.getByText('I need to reschedule my appointment')).toBeInTheDocument();
    });

    it('should display back button', () => {
      expect(screen.getByText(/Back to tickets/)).toBeInTheDocument();
    });

    it('should return to ticket list when back button is clicked', () => {
      const backButton = screen.getByText(/Back to tickets/);
      fireEvent.click(backButton);

      expect(screen.getByText('My Support Requests')).toBeInTheDocument();
      expect(screen.queryByText(/Ticket #TKT-001/)).not.toBeInTheDocument();
    });

    it('should display Conversation heading', () => {
      expect(screen.getByText('Conversation')).toBeInTheDocument();
    });

    it('should filter out internal comments', () => {
      expect(screen.getByText('We have received your request and are looking into it.')).toBeInTheDocument();
      expect(screen.getByText('Thank you for your help!')).toBeInTheDocument();
      expect(screen.queryByText('Internal note: escalate this')).not.toBeInTheDocument();
    });

    it('should display comment author names', () => {
      expect(screen.getByText('Support Staff')).toBeInTheDocument();
      expect(screen.getByText('John Doe')).toBeInTheDocument();
    });

    it('should display comment timestamps', () => {
      const timestamps = screen.getAllByText(/12\/1\/2024/);
      expect(timestamps.length).toBeGreaterThan(0);
    });

    it('should render reply form', () => {
      expect(screen.getByLabelText('Your Reply')).toBeInTheDocument();
    });

    it('should render Send Reply button', () => {
      expect(screen.getByText('Send Reply')).toBeInTheDocument();
    });

    it('should submit reply when Send Reply is clicked', async () => {
      const replyInput = screen.getByLabelText('Your Reply');
      const sendButton = screen.getByText('Send Reply');

      fireEvent.change(replyInput, { target: { value: 'My reply message' } });
      fireEvent.click(sendButton);

      await waitFor(() => {
        expect(mockCreateTicketComment).toHaveBeenCalledWith({
          ticketId: '1',
          commentData: {
            commentText: 'My reply message',
            isInternal: false,
          },
        });
      });
    });

    it('should clear reply input after submission', async () => {
      const replyInput = screen.getByLabelText('Your Reply') as HTMLTextAreaElement;
      const sendButton = screen.getByText('Send Reply');

      fireEvent.change(replyInput, { target: { value: 'My reply' } });
      fireEvent.click(sendButton);

      await waitFor(() => {
        expect(replyInput.value).toBe('');
      });
    });

    it('should disable Send Reply button when input is empty', () => {
      const sendButton = screen.getByText('Send Reply');
      expect(sendButton).toBeDisabled();
    });

    it('should enable Send Reply button when input has text', () => {
      const replyInput = screen.getByLabelText('Your Reply');
      const sendButton = screen.getByText('Send Reply');

      fireEvent.change(replyInput, { target: { value: 'Some text' } });
      expect(sendButton).not.toBeDisabled();
    });

    it('should show empty state when no comments', () => {
      mockTicketComments.mockReturnValue({
        data: [],
        isLoading: false,
      });
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const ticketButton = screen.getByText('Appointment rescheduling').closest('button');
      fireEvent.click(ticketButton!);

      expect(screen.getByText(/No replies yet/)).toBeInTheDocument();
    });

    it('should show loading state for comments', () => {
      mockTicketComments.mockReturnValue({
        data: [],
        isLoading: true,
      });
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const ticketButton = screen.getByText('Appointment rescheduling').closest('button');
      fireEvent.click(ticketButton!);

      expect(screen.getByText('Loading...')).toBeInTheDocument();
    });
  });

  describe('Closed Ticket Behavior', () => {
    beforeEach(() => {
      const closedTicket = {
        ...defaultTickets[0],
        status: 'CLOSED',
      };
      mockTickets.mockReturnValue({
        data: [closedTicket],
        isLoading: false,
        refetch: vi.fn(),
      });
      mockTicketComments.mockReturnValue({
        data: [],
        isLoading: false,
      });
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const ticketButton = screen.getByText('Appointment rescheduling').closest('button');
      fireEvent.click(ticketButton!);
    });

    it('should not show reply form for closed tickets', () => {
      expect(screen.queryByLabelText('Your Reply')).not.toBeInTheDocument();
    });

    it('should show closed ticket message', () => {
      expect(screen.getByText(/This ticket is closed/)).toBeInTheDocument();
    });

    it('should suggest opening new request for closed tickets', () => {
      expect(screen.getByText(/open a new support request/)).toBeInTheDocument();
    });
  });

  describe('Status Messages', () => {
    it('should show open status message', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const ticketButton = screen.getByText('Appointment rescheduling').closest('button');
      fireEvent.click(ticketButton!);

      expect(screen.getByText(/request has been received/)).toBeInTheDocument();
    });

    it('should show in progress status message', () => {
      const inProgressTicket = {
        ...defaultTickets[0],
        status: 'IN_PROGRESS',
      };
      mockTickets.mockReturnValue({
        data: [inProgressTicket],
        isLoading: false,
        refetch: vi.fn(),
      });
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const ticketButton = screen.getByText('Appointment rescheduling').closest('button');
      fireEvent.click(ticketButton!);

      expect(screen.getByText(/currently working on your request/)).toBeInTheDocument();
    });

    it('should show awaiting response status message', () => {
      const awaitingTicket = {
        ...defaultTickets[0],
        status: 'AWAITING_RESPONSE',
      };
      mockTickets.mockReturnValue({
        data: [awaitingTicket],
        isLoading: false,
        refetch: vi.fn(),
      });
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const ticketButton = screen.getByText('Appointment rescheduling').closest('button');
      fireEvent.click(ticketButton!);

      expect(screen.getByText(/need additional information/)).toBeInTheDocument();
    });

    it('should show resolved status message', () => {
      mockTickets.mockReturnValue({
        data: [defaultTickets[1]], // Resolved ticket
        isLoading: false,
        refetch: vi.fn(),
      });
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const ticketButton = screen.getByText('Refund request').closest('button');
      fireEvent.click(ticketButton!);

      expect(screen.getByText(/request has been resolved/)).toBeInTheDocument();
    });
  });

  describe('Status and Priority Badges', () => {
    it('should render OPEN status badge correctly', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const openBadge = screen.getByText(/open/i);
      expect(openBadge).toBeInTheDocument();
    });

    it('should render RESOLVED status badge correctly', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const resolvedBadge = screen.getByText(/resolved/i);
      expect(resolvedBadge).toBeInTheDocument();
    });

    it('should render MEDIUM priority badge correctly', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const ticketButton = screen.getByText('Appointment rescheduling').closest('button');
      fireEvent.click(ticketButton!);

      const mediumBadge = screen.getByText(/medium/i);
      expect(mediumBadge).toBeInTheDocument();
    });

    it('should render HIGH priority badge correctly', () => {
      render(React.createElement(CustomerSupport), { wrapper: createWrapper() });
      const ticketButton = screen.getByText('Refund request').closest('button');
      fireEvent.click(ticketButton!);

      const highBadge = screen.getByText(/high/i);
      expect(highBadge).toBeInTheDocument();
    });
  });
});
