/**
 * Dashboard Tests
 *
 * Tests the Dashboard component including:
 * - Metric cards (counts, rates)
 * - Success rate calculation
 * - Active workflows list (max 3)
 * - Recent activity display
 * - Empty/loading states
 * - Navigation callback
 */
import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, waitFor } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import Dashboard from './Dashboard';
import { activityService } from '../services/activity';
import { Workflow } from '../types/workflow';
import { ActivityLog } from '../types/activity';

// Mock the activity service
vi.mock('../services/activity', () => ({
  activityService: {
    getActivityLogs: vi.fn(),
  },
}));

describe('Dashboard', () => {
  const mockWorkflows: Workflow[] = [
    {
      id: 1,
      name: 'Workflow 1',
      description: '',
      status: 'active',
      trigger_type: 'wordpress/user_registration',
      draft_config: {
        trigger: { type: 'wordpress/user_registration', config: {} },
        actions: { 'action-1': { id: 'action-1', type: 'wordpress/send_email', config: {} } },
      },
      created_at: '2024-01-01T00:00:00Z',
      updated_at: '2024-01-15T00:00:00Z',
      published_version_id: null,
      last_published_at: null,
    },
    {
      id: 2,
      name: 'Workflow 2',
      description: '',
      status: 'active',
      trigger_type: 'wordpress/post_published',
      draft_config: {
        trigger: { type: 'wordpress/post_published', config: {} },
        actions: { 'action-2': { id: 'action-2', type: 'add_to_mailchimp', config: {} } },
      },
      created_at: '2024-01-02T00:00:00Z',
      updated_at: '2024-01-16T00:00:00Z',
      published_version_id: null,
      last_published_at: null,
    },
    {
      id: 3,
      name: 'Workflow 3',
      description: '',
      status: 'inactive',
      trigger_type: 'user_login',
      draft_config: {
        trigger: { type: 'user_login', config: {} },
        actions: { 'action-3': { id: 'action-3', type: 'wordpress/send_email', config: {} } },
      },
      created_at: '2024-01-03T00:00:00Z',
      updated_at: '2024-01-17T00:00:00Z',
      published_version_id: null,
      last_published_at: null,
    },
  ];

  const mockActivityLogs: ActivityLog[] = [
    {
      id: 1,
      workflow_id: 1,
      level: 'info',
      message: 'Workflow completed successfully',
      context: {},
      created_at: '2024-01-15T12:00:00Z',
    },
    {
      id: 2,
      workflow_id: 1,
      level: 'info',
      message: 'Email sent to user',
      context: {},
      created_at: '2024-01-15T11:00:00Z',
    },
    {
      id: 3,
      workflow_id: 2,
      level: 'error',
      message: 'Failed to connect to API',
      context: { error: 'Connection timeout' },
      created_at: '2024-01-15T10:00:00Z',
    },
    {
      id: 4,
      workflow_id: 1,
      level: 'info',
      message: 'Triggered by user registration',
      context: {},
      created_at: '2024-01-15T09:00:00Z',
    },
  ];

  beforeEach(() => {
    vi.clearAllMocks();
    vi.mocked(activityService.getActivityLogs).mockResolvedValue(mockActivityLogs);
  });

  // ==========================================================================
  // Basic Rendering Tests
  // ==========================================================================

  describe('basic rendering', () => {
    it('renders page title', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

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

    it('renders subtitle', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      expect(screen.getByText('Monitor your workflow automation performance')).toBeInTheDocument();
    });

    it('renders all four metric cards', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      // "Active Workflows" appears twice (stats card + list) so check for at least one
      expect(screen.getAllByText('Active Workflows').length).toBeGreaterThanOrEqual(1);
      expect(screen.getByText('Total Workflows')).toBeInTheDocument();
      expect(screen.getByText('Success Rate')).toBeInTheDocument();
      expect(screen.getByText('Total Executions')).toBeInTheDocument();
    });
  });

  // ==========================================================================
  // Metric Cards Tests
  // ==========================================================================

  describe('metric cards', () => {
    it('shows correct active/total workflow count', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      // 2 active out of 3 total
      expect(screen.getByText('2/3')).toBeInTheDocument();
    });

    it('shows correct total workflows count', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      // Total workflows is 3
      expect(screen.getByText('3')).toBeInTheDocument();
    });

    it('shows total executions count after fetching activity', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      await waitFor(() => {
        expect(screen.getByText('4')).toBeInTheDocument();
      });
    });

    it('shows 0 active workflows when none are active', async () => {
      const inactiveWorkflows = mockWorkflows.map((w) => ({ ...w, status: 'inactive' as const }));
      render(<Dashboard workflows={inactiveWorkflows} />);

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

    it('shows correct counts with empty workflows', async () => {
      render(<Dashboard workflows={[]} />);

      expect(screen.getByText('0/0')).toBeInTheDocument();
      // "0" appears for Total Workflows and Total Executions (initially)
      expect(screen.getAllByText('0').length).toBeGreaterThanOrEqual(1);
    });
  });

  // ==========================================================================
  // Success Rate Calculation Tests
  // ==========================================================================

  describe('success rate calculation', () => {
    it('calculates success rate based on info level logs', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      // 3 info logs out of 4 total = 75%
      await waitFor(() => {
        expect(screen.getByText('75.0%')).toBeInTheDocument();
      });
    });

    it('shows 0.0% when no activity', async () => {
      vi.mocked(activityService.getActivityLogs).mockResolvedValue([]);

      render(<Dashboard workflows={mockWorkflows} />);

      await waitFor(() => {
        expect(screen.getByText('0.0%')).toBeInTheDocument();
      });
    });

    it('shows 100% when all logs are info level', async () => {
      const allSuccessLogs = mockActivityLogs.map((log) => ({ ...log, level: 'info' as const }));
      vi.mocked(activityService.getActivityLogs).mockResolvedValue(allSuccessLogs);

      render(<Dashboard workflows={mockWorkflows} />);

      await waitFor(() => {
        expect(screen.getByText('100.0%')).toBeInTheDocument();
      });
    });

    it('shows 0% when all logs are error level', async () => {
      const allErrorLogs = mockActivityLogs.map((log) => ({ ...log, level: 'error' as const }));
      vi.mocked(activityService.getActivityLogs).mockResolvedValue(allErrorLogs);

      render(<Dashboard workflows={mockWorkflows} />);

      await waitFor(() => {
        expect(screen.getByText('0.0%')).toBeInTheDocument();
      });
    });
  });

  // ==========================================================================
  // Active Workflows List Tests
  // ==========================================================================

  describe('active workflows list', () => {
    it('shows empty state when no active workflows', async () => {
      const inactiveWorkflows = mockWorkflows.map((w) => ({ ...w, status: 'inactive' as const }));
      render(<Dashboard workflows={inactiveWorkflows} />);

      expect(screen.getByText('No active workflows')).toBeInTheDocument();
      expect(
        screen.getByText('Create and activate a workflow to start automating.'),
      ).toBeInTheDocument();
    });

    it('shows Create Workflow button when empty', async () => {
      const inactiveWorkflows = mockWorkflows.map((w) => ({ ...w, status: 'inactive' as const }));
      render(<Dashboard workflows={inactiveWorkflows} />);

      expect(screen.getByText('Create Workflow')).toBeInTheDocument();
    });

    it('displays active workflow names', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      expect(screen.getByText('Workflow 1')).toBeInTheDocument();
      expect(screen.getByText('Workflow 2')).toBeInTheDocument();
    });

    it('shows Active badge for each workflow', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      const badges = screen.getAllByText('Active');
      expect(badges.length).toBeGreaterThanOrEqual(2);
    });

    it('shows trigger type and action info', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      expect(screen.getByText(/wordpress\/user_registration.*1.*action/)).toBeInTheDocument();
      expect(screen.getByText(/wordpress\/post_published.*1.*action/)).toBeInTheDocument();
    });

    it('displays only first 3 active workflows', async () => {
      const manyWorkflows = [
        ...mockWorkflows,
        { ...mockWorkflows[0], id: 4, name: 'Workflow 4', status: 'active' as const },
        { ...mockWorkflows[0], id: 5, name: 'Workflow 5', status: 'active' as const },
      ];

      render(<Dashboard workflows={manyWorkflows} />);

      expect(screen.getByText('Workflow 1')).toBeInTheDocument();
      expect(screen.getByText('Workflow 2')).toBeInTheDocument();
      expect(screen.getByText('Workflow 4')).toBeInTheDocument();
      expect(screen.queryByText('Workflow 5')).not.toBeInTheDocument();
    });

    it('shows updated date for workflows', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      // The date will be formatted according to locale - multiple workflows show dates
      const dateElements = screen.getAllByText(/Updated:/);
      expect(dateElements.length).toBeGreaterThanOrEqual(1);
    });
  });

  // ==========================================================================
  // Recent Activity Tests
  // ==========================================================================

  describe('recent activity', () => {
    it('shows empty state when no activity', async () => {
      vi.mocked(activityService.getActivityLogs).mockResolvedValue([]);

      render(<Dashboard workflows={mockWorkflows} />);

      await waitFor(() => {
        expect(
          screen.getByText('No recent activity. Workflows will appear here after they execute.'),
        ).toBeInTheDocument();
      });
    });

    it('displays activity log messages', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      await waitFor(() => {
        expect(screen.getByText('Workflow completed successfully')).toBeInTheDocument();
        expect(screen.getByText('Email sent to user')).toBeInTheDocument();
        expect(screen.getByText('Failed to connect to API')).toBeInTheDocument();
      });
    });

    it('shows workflow ID for each log entry', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      await waitFor(() => {
        const workflowLabels = screen.getAllByText(/Workflow #/);
        expect(workflowLabels.length).toBe(4);
      });
    });

    it('shows timestamp for each log entry', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      await waitFor(() => {
        // Should show dates from the logs
        expect(screen.getByText('Workflow completed successfully')).toBeInTheDocument();
      });
    });
  });

  // ==========================================================================
  // Navigation Callback Tests
  // ==========================================================================

  describe('navigation callback', () => {
    it('calls onNavigate with "workflows" when Create Workflow clicked', async () => {
      const onNavigate = vi.fn();
      const inactiveWorkflows = mockWorkflows.map((w) => ({ ...w, status: 'inactive' as const }));

      render(<Dashboard workflows={inactiveWorkflows} onNavigate={onNavigate} />);

      const button = screen.getByText('Create Workflow');
      await userEvent.click(button);

      expect(onNavigate).toHaveBeenCalledWith('workflows');
    });

    it('does not throw when onNavigate is not provided', async () => {
      const inactiveWorkflows = mockWorkflows.map((w) => ({ ...w, status: 'inactive' as const }));

      render(<Dashboard workflows={inactiveWorkflows} />);

      const button = screen.getByText('Create Workflow');
      // Should not throw
      await userEvent.click(button);
    });
  });

  // ==========================================================================
  // API Fetching Tests
  // ==========================================================================

  describe('api fetching', () => {
    it('fetches activity logs on mount', async () => {
      render(<Dashboard workflows={mockWorkflows} />);

      await waitFor(() => {
        expect(activityService.getActivityLogs).toHaveBeenCalledWith({ limit: 4 });
      });
    });

    it('handles fetch error gracefully', async () => {
      const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
      vi.mocked(activityService.getActivityLogs).mockRejectedValue(new Error('API error'));

      render(<Dashboard workflows={mockWorkflows} />);

      await waitFor(() => {
        expect(consoleSpy).toHaveBeenCalledWith(
          'Error fetching recent activity:',
          expect.any(Error),
        );
      });

      // Should still render without crashing
      expect(screen.getByText('Dashboard')).toBeInTheDocument();

      consoleSpy.mockRestore();
    });
  });
});
