import React from 'react';
import { render, screen, fireEvent, waitFor } from '@testing-library/react';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import Dashboard from '../Dashboard';
import featuresReducer from '../../../store/slices/featuresSlice';
import analyticsReducer from '../../../store/slices/analyticsSlice';
import { createMockFeature, createMockAnalyticsData } from '../../../setupTests';

// Mock des hooks Redux
jest.mock('react-redux', () => ({
  ...jest.requireActual('react-redux'),
  useSelector: jest.fn(),
}));

const mockUseSelector = require('react-redux').useSelector;

describe('Dashboard Component', () => {
  let store: any;

  beforeEach(() => {
    store = configureStore({
      reducer: {
        features: featuresReducer,
        analytics: analyticsReducer,
      },
      preloadedState: {
        features: {
          features: [
            createMockFeature({ id: 'feature-1', name: 'Test Feature 1' }),
            createMockFeature({ id: 'feature-2', name: 'Test Feature 2' }),
          ],
          loading: false,
          error: null,
          selectedFeature: null,
        },
        analytics: {
          realtimeData: [
            createMockAnalyticsData({ id: 'metric-1', type: 'CPU Usage', value: 45 }),
            createMockAnalyticsData({ id: 'metric-2', type: 'Memory Usage', value: 67 }),
          ],
          dashboards: [],
          loading: false,
          error: null,
          selectedDashboard: null,
        },
      },
    });

    // Mock useSelector pour retourner les données du store
    mockUseSelector.mockImplementation((selector) => {
      const state = store.getState();
      return selector(state);
    });
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  it('renders dashboard title and description', () => {
    render(
      <Provider store={store}>
        <Dashboard />
      </Provider>
    );

    expect(screen.getByText('Dashboard')).toBeInTheDocument();
    expect(screen.getByText('Vue d\'ensemble de la plateforme Veza')).toBeInTheDocument();
  });

  it('displays feature count in stats card', () => {
    render(
      <Provider store={store}>
        <Dashboard />
      </Provider>
    );

    expect(screen.getByText('2')).toBeInTheDocument(); // 2 features
    expect(screen.getByText('Features Actives')).toBeInTheDocument();
  });

  it('displays analytics metrics count', () => {
    render(
      <Provider store={store}>
        <Dashboard />
      </Provider>
    );

    expect(screen.getByText('2')).toBeInTheDocument(); // 2 metrics
    expect(screen.getByText('Métriques Temps Réel')).toBeInTheDocument();
  });

  it('renders feature status cards', () => {
    render(
      <Provider store={store}>
        <Dashboard />
      </Provider>
    );

    expect(screen.getByText('Test Feature 1')).toBeInTheDocument();
    expect(screen.getByText('Test Feature 2')).toBeInTheDocument();
    expect(screen.getByText('test')).toBeInTheDocument(); // domain
  });

  it('displays feature metrics correctly', () => {
    render(
      <Provider store={store}>
        <Dashboard />
      </Provider>
    );

    expect(screen.getByText(/CPU: 10\.5%/)).toBeInTheDocument();
    expect(screen.getByText(/RAM: 100MB/)).toBeInTheDocument();
  });

  it('shows recent activity section', () => {
    render(
      <Provider store={store}>
        <Dashboard />
      </Provider>
    );

    expect(screen.getByText('Activité Récente')).toBeInTheDocument();
    expect(screen.getByText('Feature "Smart Recommendations" démarrée')).toBeInTheDocument();
  });

  it('handles empty features gracefully', () => {
    const emptyStore = configureStore({
      reducer: {
        features: featuresReducer,
        analytics: analyticsReducer,
      },
      preloadedState: {
        features: {
          features: [],
          loading: false,
          error: null,
          selectedFeature: null,
        },
        analytics: {
          realtimeData: [],
          dashboards: [],
          loading: false,
          error: null,
          selectedDashboard: null,
        },
      },
    });

    mockUseSelector.mockImplementation((selector) => {
      const state = emptyStore.getState();
      return selector(state);
    });

    render(
      <Provider store={emptyStore}>
        <Dashboard />
      </Provider>
    );

    expect(screen.getByText('0')).toBeInTheDocument(); // 0 features
  });

  it('handles loading state', () => {
    const loadingStore = configureStore({
      reducer: {
        features: featuresReducer,
        analytics: analyticsReducer,
      },
      preloadedState: {
        features: {
          features: [],
          loading: true,
          error: null,
          selectedFeature: null,
        },
        analytics: {
          realtimeData: [],
          dashboards: [],
          loading: true,
          error: null,
          selectedDashboard: null,
        },
      },
    });

    mockUseSelector.mockImplementation((selector) => {
      const state = loadingStore.getState();
      return selector(state);
    });

    render(
      <Provider store={loadingStore}>
        <Dashboard />
      </Provider>
    );

    // Le composant devrait toujours afficher le titre même en loading
    expect(screen.getByText('Dashboard')).toBeInTheDocument();
  });

  it('handles error state', () => {
    const errorStore = configureStore({
      reducer: {
        features: featuresReducer,
        analytics: analyticsReducer,
      },
      preloadedState: {
        features: {
          features: [],
          loading: false,
          error: 'Failed to load features',
          selectedFeature: null,
        },
        analytics: {
          realtimeData: [],
          dashboards: [],
          loading: false,
          error: 'Failed to load analytics',
          selectedDashboard: null,
        },
      },
    });

    mockUseSelector.mockImplementation((selector) => {
      const state = errorStore.getState();
      return selector(state);
    });

    render(
      <Provider store={errorStore}>
        <Dashboard />
      </Provider>
    );

    // Le composant devrait toujours afficher le titre même en erreur
    expect(screen.getByText('Dashboard')).toBeInTheDocument();
  });

  it('displays correct status badges', () => {
    const storeWithDifferentStatuses = configureStore({
      reducer: {
        features: featuresReducer,
        analytics: analyticsReducer,
      },
      preloadedState: {
        features: {
          features: [
            createMockFeature({ id: 'feature-1', status: 'running' }),
            createMockFeature({ id: 'feature-2', status: 'error' }),
            createMockFeature({ id: 'feature-3', status: 'stopped' }),
          ],
          loading: false,
          error: null,
          selectedFeature: null,
        },
        analytics: {
          realtimeData: [],
          dashboards: [],
          loading: false,
          error: null,
          selectedDashboard: null,
        },
      },
    });

    mockUseSelector.mockImplementation((selector) => {
      const state = storeWithDifferentStatuses.getState();
      return selector(state);
    });

    render(
      <Provider store={storeWithDifferentStatuses}>
        <Dashboard />
      </Provider>
    );

    expect(screen.getByText('running')).toBeInTheDocument();
    expect(screen.getByText('error')).toBeInTheDocument();
    expect(screen.getByText('stopped')).toBeInTheDocument();
  });

  it('formats memory size correctly', () => {
    const storeWithLargeMemory = configureStore({
      reducer: {
        features: featuresReducer,
        analytics: analyticsReducer,
      },
      preloadedState: {
        features: {
          features: [
            createMockFeature({
              id: 'feature-1',
              metrics: {
                cpu: 25.5,
                memory: 1024 * 1024 * 1024 * 2, // 2GB
                disk: 1024 * 1024 * 1024 * 5,    // 5GB
                network: 1024 * 1024 * 1024 * 1, // 1GB
                custom: {},
              },
            }),
          ],
          loading: false,
          error: null,
          selectedFeature: null,
        },
        analytics: {
          realtimeData: [],
          dashboards: [],
          loading: false,
          error: null,
          selectedDashboard: null,
        },
      },
    });

    mockUseSelector.mockImplementation((selector) => {
      const state = storeWithLargeMemory.getState();
      return selector(state);
    });

    render(
      <Provider store={storeWithLargeMemory}>
        <Dashboard />
      </Provider>
    );

    expect(screen.getByText(/RAM: 2048MB/)).toBeInTheDocument();
  });

  it('handles action buttons', () => {
    render(
      <Provider store={store}>
        <Dashboard />
      </Provider>
    );

    const newFeatureButton = screen.getByText('Nouveau Feature');
    const refreshButton = screen.getByText('Actualiser');

    expect(newFeatureButton).toBeInTheDocument();
    expect(refreshButton).toBeInTheDocument();

    // Test des clics (pour l'instant sans action réelle)
    fireEvent.click(newFeatureButton);
    fireEvent.click(refreshButton);
  });

  it('displays correct domain icons', () => {
    const storeWithDifferentDomains = configureStore({
      reducer: {
        features: featuresReducer,
        analytics: analyticsReducer,
      },
      preloadedState: {
        features: {
          features: [
            createMockFeature({ id: 'feature-1', domain: 'user' }),
            createMockFeature({ id: 'feature-2', domain: 'communication' }),
            createMockFeature({ id: 'feature-3', domain: 'media' }),
            createMockFeature({ id: 'feature-4', domain: 'ai' }),
            createMockFeature({ id: 'feature-5', domain: 'analytics' }),
            createMockFeature({ id: 'feature-6', domain: 'integration' }),
          ],
          loading: false,
          error: null,
          selectedFeature: null,
        },
        analytics: {
          realtimeData: [],
          dashboards: [],
          loading: false,
          error: null,
          selectedDashboard: null,
        },
      },
    });

    mockUseSelector.mockImplementation((selector) => {
      const state = storeWithDifferentDomains.getState();
      return selector(state);
    });

    render(
      <Provider store={storeWithDifferentDomains}>
        <Dashboard />
      </Provider>
    );

    // Vérifier que les domaines sont affichés
    expect(screen.getByText('user')).toBeInTheDocument();
    expect(screen.getByText('communication')).toBeInTheDocument();
    expect(screen.getByText('media')).toBeInTheDocument();
    expect(screen.getByText('ai')).toBeInTheDocument();
    expect(screen.getByText('analytics')).toBeInTheDocument();
    expect(screen.getByText('integration')).toBeInTheDocument();
  });
});

// Helper function pour créer des données d'analytics mock
export const createMockAnalyticsData = (overrides = {}) => ({
  id: 'metric-1',
  type: 'Test Metric',
  value: 50,
  timestamp: new Date().toISOString(),
  metadata: {},
  ...overrides,
}); 