import { render, screen, waitFor } from '@testing-library/react';
import { describe, it, expect, vi, beforeEach } from 'vitest';
import userEvent from '@testing-library/user-event';
import '@testing-library/jest-dom/vitest';
import { Dialog, DialogBody, DialogFooter, DialogHeader } from './dialog';

describe('Dialog Component', () => {
  const mockOnClose = vi.fn();

  beforeEach(() => {
    vi.clearAllMocks();
    document.body.style.overflow = '';
  });

  it('renders nothing when open is false', () => {
    render(
      <Dialog open={false} onClose={mockOnClose} title="Test Dialog">
        <div>Dialog content</div>
      </Dialog>,
    );

    expect(screen.queryByText('Dialog content')).not.toBeInTheDocument();
  });

  it('renders dialog when open is true', () => {
    render(
      <Dialog open={true} onClose={mockOnClose} title="Test Dialog">
        <div>Dialog content</div>
      </Dialog>,
    );

    expect(screen.getByText('Dialog content')).toBeInTheDocument();
    expect(screen.getByText('Test Dialog')).toBeInTheDocument();
  });

  it('displays title when provided', () => {
    render(
      <Dialog open={true} onClose={mockOnClose} title="Test Dialog">
        <div>Dialog content</div>
      </Dialog>,
    );

    expect(screen.getByText('Test Dialog')).toBeInTheDocument();
  });

  it('renders DialogHeader correctly', () => {
    render(
      <Dialog open={true} onClose={mockOnClose} title="Test Dialog">
        <div>Dialog content</div>
      </Dialog>,
    );

    const header = screen.getByText('Test Dialog').closest('.border-b');
    expect(header).toBeInTheDocument();
  });

  it('renders DialogBody correctly', () => {
    render(
      <Dialog open={true} onClose={mockOnClose} title="Test Dialog">
        <div>Dialog content</div>
      </Dialog>,
    );

    expect(screen.getByText('Dialog content')).toBeInTheDocument();
  });

  it('renders custom footer when provided', () => {
    render(
      <Dialog
        open={true}
        onClose={mockOnClose}
        title="Test Dialog"
        footer={<button>Custom Footer</button>}
      >
        <div>Dialog content</div>
      </Dialog>,
    );

    expect(screen.getByText('Custom Footer')).toBeInTheDocument();
  });

  it('shows default footer with confirm and cancel buttons for confirm variant', () => {
    const mockOnConfirm = vi.fn();
    render(
      <Dialog
        open={true}
        onClose={mockOnClose}
        title="Confirm Dialog"
        variant="confirm"
        onConfirm={mockOnConfirm}
        showCancel={true}
      >
        <div>Are you sure?</div>
      </Dialog>,
    );

    expect(screen.getByText('Confirm')).toBeInTheDocument();
    expect(screen.getByText('Cancel')).toBeInTheDocument();
  });

  it('calls onConfirm when confirm button is clicked', async () => {
    const user = userEvent.setup();
    const mockOnConfirm = vi.fn();
    render(
      <Dialog
        open={true}
        onClose={mockOnClose}
        title="Confirm Dialog"
        variant="confirm"
        onConfirm={mockOnConfirm}
      >
        <div>Are you sure?</div>
      </Dialog>,
    );

    const confirmButton = screen.getByText('Confirm');
    await user.click(confirmButton);

    expect(mockOnConfirm).toHaveBeenCalledTimes(1);
    expect(mockOnClose).toHaveBeenCalledTimes(1);
  });

  it('calls onCancel when cancel button is clicked', async () => {
    const user = userEvent.setup();
    const mockOnCancel = vi.fn();
    render(
      <Dialog
        open={true}
        onClose={mockOnClose}
        title="Confirm Dialog"
        variant="confirm"
        onCancel={mockOnCancel}
        showCancel={true}
      >
        <div>Are you sure?</div>
      </Dialog>,
    );

    const cancelButton = screen.getByText('Cancel');
    await user.click(cancelButton);

    expect(mockOnCancel).toHaveBeenCalledTimes(1);
    expect(mockOnClose).toHaveBeenCalledTimes(1);
  });

  it('shows alert icon for alert variant', () => {
    render(
      <Dialog
        open={true}
        onClose={mockOnClose}
        title="Alert Dialog"
        variant="alert"
      >
        <div>Alert message</div>
      </Dialog>,
    );

    const icon = screen
      .getByText('Alert Dialog')
      .closest('.border-b')
      ?.querySelector('svg');
    expect(icon).toBeInTheDocument();
  });

  it('shows info icon for info variant', () => {
    render(
      <Dialog
        open={true}
        onClose={mockOnClose}
        title="Info Dialog"
        variant="info"
      >
        <div>Info message</div>
      </Dialog>,
    );

    const icon = screen
      .getByText('Info Dialog')
      .closest('.border-b')
      ?.querySelector('svg');
    expect(icon).toBeInTheDocument();
  });

  it('applies destructive variant to confirm button for alert', () => {
    const mockOnConfirm = vi.fn();
    render(
      <Dialog
        open={true}
        onClose={mockOnClose}
        title="Alert Dialog"
        variant="alert"
        onConfirm={mockOnConfirm}
      >
        <div>Alert message</div>
      </Dialog>,
    );

    const confirmButton = screen.getByText('Confirm');
    const buttonElement = confirmButton.closest('button');
    // Vérifier que le bouton a les classes de variant destructive
    expect(
      buttonElement?.classList.contains('bg-destructive') ||
        buttonElement?.classList.contains('text-destructive-foreground'),
    ).toBe(true);
  });

  it('uses custom confirm and cancel labels', () => {
    const mockOnConfirm = vi.fn();
    render(
      <Dialog
        open={true}
        onClose={mockOnClose}
        title="Confirm Dialog"
        variant="confirm"
        onConfirm={mockOnConfirm}
        confirmLabel="Yes"
        cancelLabel="No"
        showCancel={true}
      >
        <div>Are you sure?</div>
      </Dialog>,
    );

    expect(screen.getByText('Yes')).toBeInTheDocument();
    expect(screen.getByText('No')).toBeInTheDocument();
  });

  it('hides cancel button when showCancel is false', () => {
    const mockOnConfirm = vi.fn();
    render(
      <Dialog
        open={true}
        onClose={mockOnClose}
        title="Confirm Dialog"
        variant="confirm"
        onConfirm={mockOnConfirm}
        showCancel={false}
      >
        <div>Are you sure?</div>
      </Dialog>,
    );

    expect(screen.queryByText('Cancel')).not.toBeInTheDocument();
    expect(screen.getByText('Confirm')).toBeInTheDocument();
  });

  it('does not show footer for default variant without footer or actions', () => {
    render(
      <Dialog open={true} onClose={mockOnClose} title="Default Dialog">
        <div>Dialog content</div>
      </Dialog>,
    );

    const footer = document.querySelector('.border-t');
    expect(footer).not.toBeInTheDocument();
  });

  it('handles async onConfirm', async () => {
    const user = userEvent.setup();
    const mockOnConfirm = vi.fn().mockResolvedValue(undefined);
    render(
      <Dialog
        open={true}
        onClose={mockOnClose}
        title="Confirm Dialog"
        variant="confirm"
        onConfirm={mockOnConfirm}
      >
        <div>Are you sure?</div>
      </Dialog>,
    );

    const confirmButton = screen.getByText('Confirm');
    await user.click(confirmButton);

    await waitFor(() => {
      expect(mockOnConfirm).toHaveBeenCalledTimes(1);
    });

    await waitFor(() => {
      expect(mockOnClose).toHaveBeenCalledTimes(1);
    });
  });

  describe('DialogHeader', () => {
    it('renders DialogHeader correctly', () => {
      render(
        <Dialog open={true} onClose={mockOnClose}>
          <DialogHeader>
            <div>Header content</div>
          </DialogHeader>
          <DialogBody>
            <div>Body content</div>
          </DialogBody>
        </Dialog>,
      );

      expect(screen.getByText('Header content')).toBeInTheDocument();
    });
  });

  describe('DialogBody', () => {
    it('renders DialogBody correctly', () => {
      render(
        <Dialog open={true} onClose={mockOnClose}>
          <DialogBody>
            <div>Body content</div>
          </DialogBody>
        </Dialog>,
      );

      expect(screen.getByText('Body content')).toBeInTheDocument();
    });
  });

  describe('DialogFooter', () => {
    it('renders DialogFooter correctly', () => {
      render(
        <Dialog open={true} onClose={mockOnClose}>
          <DialogBody>
            <div>Body content</div>
          </DialogBody>
          <DialogFooter>
            <button>Footer button</button>
          </DialogFooter>
        </Dialog>,
      );

      expect(screen.getByText('Footer button')).toBeInTheDocument();
    });
  });
});
