import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import EmailComposer from '../EmailComposer';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import type { StaffEmail } from '../../../types';

// Mock react-i18next
vi.mock('react-i18next', () => ({
  useTranslation: () => ({
    t: (key: string) => key,
  }),
}));

// Mock react-hot-toast
vi.mock('react-hot-toast', () => ({
  default: {
    success: vi.fn(),
    error: vi.fn(),
  },
}));

// Mock hooks
vi.mock('../../../hooks/useStaffEmail', () => ({
  useCreateDraft: vi.fn(() => ({
    mutateAsync: vi.fn(),
    isPending: false,
  })),
  useUpdateDraft: vi.fn(() => ({
    mutateAsync: vi.fn(),
    isPending: false,
  })),
  useSendEmail: vi.fn(() => ({
    mutateAsync: vi.fn(),
    isPending: false,
  })),
  useUploadAttachment: vi.fn(() => ({
    mutateAsync: vi.fn(),
  })),
  useContactSearch: vi.fn(() => ({
    data: [],
  })),
  useUserEmailAddresses: vi.fn(() => ({
    data: [
      {
        id: 1,
        email_address: 'test@example.com',
        display_name: 'Test User',
      },
    ],
  })),
}));

describe('EmailComposer', () => {
  const defaultProps = {
    onClose: vi.fn(),
    onSent: vi.fn(),
  };

  const mockReplyToEmail: StaffEmail = {
    id: 1,
    owner: 1,
    emailAddress: 1,
    folder: 1,
    fromAddress: 'sender@example.com',
    fromName: 'Sender Name',
    toAddresses: ['test@example.com'],
    ccAddresses: [],
    bccAddresses: [],
    subject: 'Original Subject',
    snippet: 'Email snippet',
    bodyText: 'Original email body',
    bodyHtml: '<p>Original email body</p>',
    messageId: 'message-123',
    inReplyTo: null,
    references: '',
    status: 'SENT',
    threadId: 'thread-123',
    emailDate: '2025-01-15T10:00:00Z',
    isRead: true,
    isStarred: false,
    isImportant: false,
    isAnswered: false,
    isPermanentlyDeleted: false,
    deletedAt: null,
    hasAttachments: false,
    attachmentCount: 0,
    attachments: [],
    labels: [],
    createdAt: '2025-01-15T10:00:00Z',
    updatedAt: '2025-01-15T10:00:00Z',
  };

  const createWrapper = () => {
    const queryClient = new QueryClient({
      defaultOptions: {
        queries: { retry: false },
        mutations: { retry: false },
      },
    });
    return ({ children }: { children: React.ReactNode }) => (
      <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
    );
  };

  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('renders new message mode', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });
    expect(screen.getByText('New Message')).toBeInTheDocument();
  });

  it('renders reply mode with subject prefixed', () => {
    render(<EmailComposer {...defaultProps} replyTo={mockReplyToEmail} />, {
      wrapper: createWrapper(),
    });
    expect(screen.getByText('Reply')).toBeInTheDocument();
    expect(screen.getByDisplayValue('Re: Original Subject')).toBeInTheDocument();
  });

  it('renders forward mode with subject prefixed', () => {
    render(<EmailComposer {...defaultProps} forwardFrom={mockReplyToEmail} />, {
      wrapper: createWrapper(),
    });
    expect(screen.getByText('Forward')).toBeInTheDocument();
    expect(screen.getByDisplayValue('Fwd: Original Subject')).toBeInTheDocument();
  });

  it('populates recipient in reply mode', () => {
    render(<EmailComposer {...defaultProps} replyTo={mockReplyToEmail} />, {
      wrapper: createWrapper(),
    });
    expect(screen.getByDisplayValue('sender@example.com')).toBeInTheDocument();
  });

  it('renders minimized state', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    const buttons = screen.getAllByRole('button');
    const minimizeButton = buttons.find((btn) =>
      btn.querySelector('svg')?.classList.contains('lucide-minimize-2')
    );
    if (minimizeButton) {
      fireEvent.click(minimizeButton);
    }

    expect(screen.getByText('New Message')).toBeInTheDocument();
  });

  it('expands from minimized state', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    // Minimize
    let buttons = screen.getAllByRole('button');
    const minimizeButton = buttons.find((btn) =>
      btn.querySelector('svg')?.classList.contains('lucide-minimize-2')
    );
    if (minimizeButton) {
      fireEvent.click(minimizeButton);
    }

    // Maximize
    buttons = screen.getAllByRole('button');
    const maximizeButton = buttons.find((btn) =>
      btn.querySelector('svg')?.classList.contains('lucide-maximize-2')
    );
    if (maximizeButton) {
      fireEvent.click(maximizeButton);
    }

    expect(screen.getByPlaceholderText('recipient@example.com')).toBeInTheDocument();
  });

  it('calls onClose when close button clicked', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    const buttons = screen.getAllByRole('button');
    const closeButton = buttons.find((btn) =>
      btn.querySelector('svg')?.classList.contains('lucide-x')
    );
    if (closeButton) {
      fireEvent.click(closeButton);
    }

    expect(defaultProps.onClose).toHaveBeenCalled();
  });

  it('shows Cc field when Cc button clicked', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    const ccButton = screen.getByText('Cc');
    fireEvent.click(ccButton);

    expect(screen.getByPlaceholderText('cc@example.com')).toBeInTheDocument();
  });

  it('shows Bcc field when Bcc button clicked', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    const bccButton = screen.getByText('Bcc');
    fireEvent.click(bccButton);

    expect(screen.getByPlaceholderText('bcc@example.com')).toBeInTheDocument();
  });

  it('updates subject field', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    const subjectInput = screen.getByPlaceholderText('Email subject');
    fireEvent.change(subjectInput, { target: { value: 'Test Subject' } });

    expect(subjectInput).toHaveValue('Test Subject');
  });

  it('updates body field', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    const bodyTextarea = screen.getByPlaceholderText('Write your message...');
    fireEvent.change(bodyTextarea, { target: { value: 'Test email body' } });

    expect(bodyTextarea).toHaveValue('Test email body');
  });

  it('updates to field', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    const toInput = screen.getByPlaceholderText('recipient@example.com');
    fireEvent.change(toInput, { target: { value: 'test@example.com' } });

    expect(toInput).toHaveValue('test@example.com');
  });

  it('updates cc field when shown', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    fireEvent.click(screen.getByText('Cc'));
    const ccInput = screen.getByPlaceholderText('cc@example.com');
    fireEvent.change(ccInput, { target: { value: 'cc@example.com' } });

    expect(ccInput).toHaveValue('cc@example.com');
  });

  it('updates bcc field when shown', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    fireEvent.click(screen.getByText('Bcc'));
    const bccInput = screen.getByPlaceholderText('bcc@example.com');
    fireEvent.change(bccInput, { target: { value: 'bcc@example.com' } });

    expect(bccInput).toHaveValue('bcc@example.com');
  });

  it('renders send button', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    expect(screen.getByText('staffEmail.send')).toBeInTheDocument();
  });

  it('renders save draft button', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    expect(screen.getByText('Save draft')).toBeInTheDocument();
  });

  it('renders formatting buttons', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    const buttons = screen.getAllByRole('button');
    const boldButton = buttons.find((btn) =>
      btn.querySelector('svg')?.classList.contains('lucide-bold')
    );
    const italicButton = buttons.find((btn) =>
      btn.querySelector('svg')?.classList.contains('lucide-italic')
    );
    const underlineButton = buttons.find((btn) =>
      btn.querySelector('svg')?.classList.contains('lucide-underline')
    );

    expect(boldButton).toBeInTheDocument();
    expect(italicButton).toBeInTheDocument();
    expect(underlineButton).toBeInTheDocument();
  });

  it('renders attachment button', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    // Attachment input is wrapped in a label, not a button
    const paperclipIcons = document.querySelectorAll('.lucide-paperclip');
    expect(paperclipIcons.length).toBeGreaterThan(0);
  });

  it('renders discard button', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    const buttons = screen.getAllByRole('button');
    const discardButton = buttons.find((btn) =>
      btn.querySelector('svg')?.classList.contains('lucide-trash-2')
    );

    expect(discardButton).toBeInTheDocument();
  });

  it('renders from address selector', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    expect(screen.getByText('From:')).toBeInTheDocument();
    expect(screen.getByRole('combobox')).toBeInTheDocument();
  });

  it('populates from address with default value', async () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    await waitFor(() => {
      const select = screen.getByRole('combobox');
      expect(select).toHaveValue('1');
    });
  });

  it('does not add Re: prefix if subject already has it', () => {
    const emailWithReply = {
      ...mockReplyToEmail,
      subject: 'Re: Already Replied',
    };

    render(<EmailComposer {...defaultProps} replyTo={emailWithReply} />, {
      wrapper: createWrapper(),
    });

    expect(screen.getByDisplayValue('Re: Already Replied')).toBeInTheDocument();
  });

  it('does not add Fwd: prefix if subject already has it', () => {
    const emailWithFwd = {
      ...mockReplyToEmail,
      subject: 'Fwd: Already Forwarded',
    };

    render(<EmailComposer {...defaultProps} forwardFrom={emailWithFwd} />, {
      wrapper: createWrapper(),
    });

    expect(screen.getByDisplayValue('Fwd: Already Forwarded')).toBeInTheDocument();
  });

  it('includes original message in reply body', () => {
    render(<EmailComposer {...defaultProps} replyTo={mockReplyToEmail} />, {
      wrapper: createWrapper(),
    });

    const bodyTextarea = screen.getByPlaceholderText('Write your message...');
    const value = (bodyTextarea as HTMLTextAreaElement).value;
    expect(value).toContain('Original email body');
  });

  it('includes original message in forward body', () => {
    render(<EmailComposer {...defaultProps} forwardFrom={mockReplyToEmail} />, {
      wrapper: createWrapper(),
    });

    const bodyTextarea = screen.getByPlaceholderText('Write your message...');
    const value = (bodyTextarea as HTMLTextAreaElement).value;
    expect(value).toContain('Original email body');
  });

  it('renders with all header fields', () => {
    render(<EmailComposer {...defaultProps} />, { wrapper: createWrapper() });

    expect(screen.getByText('From:')).toBeInTheDocument();
    expect(screen.getByText('To:')).toBeInTheDocument();
    expect(screen.getByText('Subject:')).toBeInTheDocument();
  });
});
