import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor, fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { TrackShareDialog } from './TrackShareDialog';
import { createShare, TrackShareError } from '../services/trackShareService';
import { useToast } from '@/hooks/useToast';

// Mock dependencies
vi.mock('../services/trackShareService');
vi.mock('@/hooks/useToast');

describe('TrackShareDialog', () => {
  const mockOnClose = vi.fn();
  const mockToast = {
    success: vi.fn(),
    error: vi.fn(),
    warning: vi.fn(),
    info: vi.fn(),
    toast: vi.fn(),
  };

  beforeEach(() => {
    vi.clearAllMocks();
    vi.mocked(useToast).mockReturnValue(mockToast);
  });

  it('should render dialog when open', () => {
    render(
      <TrackShareDialog open={true} onClose={mockOnClose} trackId={123} />,
    );

    expect(screen.getByText('Partager le track')).toBeInTheDocument();
    expect(screen.getByText('Permissions')).toBeInTheDocument();
    expect(screen.getByLabelText(/Lecture/)).toBeInTheDocument();
    expect(screen.getByLabelText(/Téléchargement/)).toBeInTheDocument();
  });

  it('should not render when closed', () => {
    render(
      <TrackShareDialog open={false} onClose={mockOnClose} trackId={123} />,
    );

    expect(screen.queryByText('Partager le track')).not.toBeInTheDocument();
  });

  it('should create share with read permission', async () => {
    const mockShare = {
      id: 1,
      track_id: 123,
      user_id: 456,
      share_token: 'test-token-123',
      permissions: 'read',
      access_count: 0,
      created_at: '2024-01-01T00:00:00Z',
      updated_at: '2024-01-01T00:00:00Z',
    };

    vi.mocked(createShare).mockResolvedValue(mockShare);

    render(
      <TrackShareDialog open={true} onClose={mockOnClose} trackId={123} />,
    );

    const createButton = screen.getByText(/Créer le lien de partage/i);
    await userEvent.click(createButton);

    await waitFor(() => {
      expect(createShare).toHaveBeenCalledWith(123, {
        permissions: 'read',
        expires_at: undefined,
      });
    });
  });

  it('should create share with both permissions', async () => {
    const mockShare = {
      id: 1,
      track_id: 123,
      user_id: 456,
      share_token: 'test-token-123',
      permissions: 'read,download',
      access_count: 0,
      created_at: '2024-01-01T00:00:00Z',
      updated_at: '2024-01-01T00:00:00Z',
    };

    vi.mocked(createShare).mockResolvedValue(mockShare);

    render(
      <TrackShareDialog open={true} onClose={mockOnClose} trackId={123} />,
    );

    // Check download permission
    const downloadCheckbox = screen.getByLabelText(/Téléchargement/);
    await userEvent.click(downloadCheckbox);

    const createButton = screen.getByText(/Créer le lien de partage/i);
    await userEvent.click(createButton);

    await waitFor(() => {
      expect(createShare).toHaveBeenCalledWith(123, {
        permissions: 'read,download',
        expires_at: undefined,
      });
    });
  });

  it('should display error when creation fails', async () => {
    const error = new TrackShareError('Failed to create share', 'SERVER', true);
    vi.mocked(createShare).mockRejectedValue(error);

    render(
      <TrackShareDialog open={true} onClose={mockOnClose} trackId={123} />,
    );

    const createButton = screen.getByText(/Créer le lien de partage/i);
    await userEvent.click(createButton);

    await waitFor(() => {
      expect(screen.getByText(/Failed to create share/i)).toBeInTheDocument();
    });
  });

  it('should display share link after creation', async () => {
    const mockShare = {
      id: 1,
      track_id: 123,
      user_id: 456,
      share_token: 'test-token-123',
      permissions: 'read',
      access_count: 0,
      created_at: '2024-01-01T00:00:00Z',
      updated_at: '2024-01-01T00:00:00Z',
    };

    vi.mocked(createShare).mockResolvedValue(mockShare);

    render(
      <TrackShareDialog open={true} onClose={mockOnClose} trackId={123} />,
    );

    const createButton = screen.getByText(/Créer le lien de partage/i);
    await userEvent.click(createButton);

    await waitFor(() => {
      expect(screen.getByText(/Lien de partage/i)).toBeInTheDocument();
    });
  });

  it('should validate that at least one permission is selected', async () => {
    render(
      <TrackShareDialog open={true} onClose={mockOnClose} trackId={123} />,
    );

    // Uncheck read permission
    const readCheckbox = screen.getByLabelText(/Lecture/);
    await userEvent.click(readCheckbox);

    const createButton = screen.getByText(/Créer le lien de partage/i);
    expect(createButton).toBeDisabled();
  });
});
