/**
 * Workflow Service Tests
 *
 * Tests the workflow CRUD API service including:
 * - getWorkflows with filters
 * - getWorkflow single
 * - createWorkflow
 * - updateWorkflow
 * - renameWorkflow
 * - deleteWorkflow
 * - activate/deactivate
 * - getTriggers/getActions
 */
import { describe, it, expect, vi, beforeEach } from 'vitest';
import {
  getWorkflows,
  getWorkflow,
  createWorkflow,
  updateWorkflow,
  renameWorkflow,
  deleteWorkflow,
  activateWorkflow,
  deactivateWorkflow,
  getTriggers,
  getActions,
  workflowService,
} from './workflows';

// Mock the apiRequest function
vi.mock('./api', () => ({
  apiRequest: vi.fn(),
}));

import { apiRequest } from './api';

describe('workflow service', () => {
  const mockWorkflow = {
    id: 1,
    name: 'Test Workflow',
    status: 'active',
    trigger_type: 'wordpress/user_registration',
    config: { action: { type: 'wordpress/send_email' } },
    created_at: '2024-01-01T00:00:00Z',
    updated_at: '2024-01-15T00:00:00Z',
  };

  const mockWorkflows = [
    mockWorkflow,
    { ...mockWorkflow, id: 2, name: 'Workflow 2', status: 'inactive' },
  ];

  const mockTriggers = [
    {
      type: 'wordpress/user_registration',
      label: 'User Registration',
      description: 'Fires when a new user registers',
      app_service: 'wordpress',
    },
    {
      type: 'wordpress/post_published',
      label: 'Post Published',
      description: 'Fires when a post is published',
      app_service: 'wordpress',
    },
  ];

  const mockActions = [
    {
      type: 'wordpress/send_email',
      label: 'Send Email',
      description: 'Send an email message',
      app_service: 'wordpress',
      schema: [],
    },
    {
      type: 'wordpress/create_post',
      label: 'Create Post',
      description: 'Create a new WordPress post',
      app_service: 'wordpress',
      schema: [],
    },
  ];

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

  // ==========================================================================
  // getWorkflows Tests
  // ==========================================================================

  describe('getWorkflows', () => {
    it('fetches workflows without filters', async () => {
      vi.mocked(apiRequest).mockResolvedValue(mockWorkflows);

      const result = await getWorkflows();

      expect(apiRequest).toHaveBeenCalledWith('/workflows', { method: 'GET' });
      expect(result).toEqual(mockWorkflows);
    });

    it('includes status filter in query params', async () => {
      vi.mocked(apiRequest).mockResolvedValue(mockWorkflows);

      await getWorkflows({ status: 'active' });

      expect(apiRequest).toHaveBeenCalledWith('/workflows?status=active', { method: 'GET' });
    });

    it('includes trigger_type filter in query params', async () => {
      vi.mocked(apiRequest).mockResolvedValue(mockWorkflows);

      await getWorkflows({ trigger_type: 'wordpress/user_registration' });

      expect(apiRequest).toHaveBeenCalledWith('/workflows?trigger_type=wordpress%2Fuser_registration', {
        method: 'GET',
      });
    });

    it('includes page filter in query params', async () => {
      vi.mocked(apiRequest).mockResolvedValue(mockWorkflows);

      await getWorkflows({ page: 2 });

      expect(apiRequest).toHaveBeenCalledWith('/workflows?page=2', { method: 'GET' });
    });

    it('includes per_page filter in query params', async () => {
      vi.mocked(apiRequest).mockResolvedValue(mockWorkflows);

      await getWorkflows({ per_page: 25 });

      expect(apiRequest).toHaveBeenCalledWith('/workflows?per_page=25', { method: 'GET' });
    });

    it('combines multiple filters in query params', async () => {
      vi.mocked(apiRequest).mockResolvedValue(mockWorkflows);

      await getWorkflows({
        status: 'active',
        trigger_type: 'wordpress/post_published',
        page: 1,
        per_page: 10,
      });

      expect(apiRequest).toHaveBeenCalledWith(
        '/workflows?status=active&trigger_type=wordpress%2Fpost_published&page=1&per_page=10',
        { method: 'GET' },
      );
    });
  });

  // ==========================================================================
  // getWorkflow Tests
  // ==========================================================================

  describe('getWorkflow', () => {
    it('fetches a single workflow by ID', async () => {
      vi.mocked(apiRequest).mockResolvedValue(mockWorkflow);

      const result = await getWorkflow(1);

      expect(apiRequest).toHaveBeenCalledWith('/workflows/1', { method: 'GET' });
      expect(result).toEqual(mockWorkflow);
    });

    it('fetches different workflow IDs', async () => {
      vi.mocked(apiRequest).mockResolvedValue(mockWorkflows[1]);

      await getWorkflow(42);

      expect(apiRequest).toHaveBeenCalledWith('/workflows/42', { method: 'GET' });
    });
  });

  // ==========================================================================
  // createWorkflow Tests
  // ==========================================================================

  describe('createWorkflow', () => {
    it('creates a new workflow', async () => {
      const newWorkflow = { name: 'New Workflow', trigger_type: 'user_login' };
      vi.mocked(apiRequest).mockResolvedValue({ ...mockWorkflow, ...newWorkflow, id: 3 });

      const result = await createWorkflow(newWorkflow);

      expect(apiRequest).toHaveBeenCalledWith('/workflows', {
        method: 'POST',
        body: JSON.stringify(newWorkflow),
      });
      expect(result.name).toBe('New Workflow');
    });

    it('creates workflow with full config', async () => {
      const fullConfig = {
        name: 'Full Workflow',
        trigger_type: 'wordpress/post_published',
        config: { action: { type: 'wordpress/send_email', config: { to: 'test@example.com' } } },
      };
      vi.mocked(apiRequest).mockResolvedValue({ ...mockWorkflow, ...fullConfig });

      await createWorkflow(fullConfig as any);

      expect(apiRequest).toHaveBeenCalledWith('/workflows', {
        method: 'POST',
        body: JSON.stringify(fullConfig),
      });
    });
  });

  // ==========================================================================
  // updateWorkflow Tests
  // ==========================================================================

  describe('updateWorkflow', () => {
    it('updates an existing workflow', async () => {
      const updates = { name: 'Updated Workflow', config: { action: { type: 'wordpress/create_post' } } };
      vi.mocked(apiRequest).mockResolvedValue({ ...mockWorkflow, ...updates });

      const result = await updateWorkflow(1, updates as any);

      expect(apiRequest).toHaveBeenCalledWith('/workflows/1', {
        method: 'PUT',
        body: JSON.stringify(updates),
      });
      expect(result.name).toBe('Updated Workflow');
    });

    it('updates workflow with partial data', async () => {
      const partialUpdate = { status: 'inactive' as const };
      vi.mocked(apiRequest).mockResolvedValue({ ...mockWorkflow, ...partialUpdate });

      await updateWorkflow(1, partialUpdate);

      expect(apiRequest).toHaveBeenCalledWith('/workflows/1', {
        method: 'PUT',
        body: JSON.stringify(partialUpdate),
      });
    });
  });

  // ==========================================================================
  // renameWorkflow Tests
  // ==========================================================================

  describe('renameWorkflow', () => {
    it('renames a workflow', async () => {
      vi.mocked(apiRequest).mockResolvedValue({ ...mockWorkflow, name: 'Renamed Workflow' });

      const result = await renameWorkflow(1, 'Renamed Workflow');

      expect(apiRequest).toHaveBeenCalledWith('/workflows/1', {
        method: 'PUT',
        body: JSON.stringify({ name: 'Renamed Workflow' }),
      });
      expect(result.name).toBe('Renamed Workflow');
    });

    it('renames different workflow IDs', async () => {
      vi.mocked(apiRequest).mockResolvedValue({ ...mockWorkflow, id: 99, name: 'New Name' });

      await renameWorkflow(99, 'New Name');

      expect(apiRequest).toHaveBeenCalledWith('/workflows/99', {
        method: 'PUT',
        body: JSON.stringify({ name: 'New Name' }),
      });
    });
  });

  // ==========================================================================
  // deleteWorkflow Tests
  // ==========================================================================

  describe('deleteWorkflow', () => {
    it('deletes a workflow', async () => {
      vi.mocked(apiRequest).mockResolvedValue(undefined);

      await deleteWorkflow(1);

      expect(apiRequest).toHaveBeenCalledWith('/workflows/1', { method: 'DELETE' });
    });

    it('deletes different workflow IDs', async () => {
      vi.mocked(apiRequest).mockResolvedValue(undefined);

      await deleteWorkflow(42);

      expect(apiRequest).toHaveBeenCalledWith('/workflows/42', { method: 'DELETE' });
    });
  });

  // ==========================================================================
  // activateWorkflow Tests
  // ==========================================================================

  describe('activateWorkflow', () => {
    it('activates a workflow', async () => {
      vi.mocked(apiRequest).mockResolvedValue({ ...mockWorkflow, status: 'active' });

      const result = await activateWorkflow(1);

      expect(apiRequest).toHaveBeenCalledWith('/workflows/1/activate', { method: 'POST' });
      expect(result.status).toBe('active');
    });
  });

  // ==========================================================================
  // deactivateWorkflow Tests
  // ==========================================================================

  describe('deactivateWorkflow', () => {
    it('deactivates a workflow', async () => {
      vi.mocked(apiRequest).mockResolvedValue({ ...mockWorkflow, status: 'inactive' });

      const result = await deactivateWorkflow(1);

      expect(apiRequest).toHaveBeenCalledWith('/workflows/1/deactivate', { method: 'POST' });
      expect(result.status).toBe('inactive');
    });
  });

  // ==========================================================================
  // getTriggers Tests
  // ==========================================================================

  describe('getTriggers', () => {
    it('fetches all triggers', async () => {
      vi.mocked(apiRequest).mockResolvedValue(mockTriggers);

      const result = await getTriggers();

      expect(apiRequest).toHaveBeenCalledWith('/triggers', { method: 'GET' });
      expect(result).toEqual(mockTriggers);
      expect(result.length).toBe(2);
    });
  });

  // ==========================================================================
  // getActions Tests
  // ==========================================================================

  describe('getActions', () => {
    it('fetches all actions', async () => {
      vi.mocked(apiRequest).mockResolvedValue(mockActions);

      const result = await getActions();

      expect(apiRequest).toHaveBeenCalledWith('/actions', { method: 'GET' });
      expect(result).toEqual(mockActions);
      expect(result.length).toBe(2);
    });
  });

  // ==========================================================================
  // workflowService Object Tests
  // ==========================================================================

  describe('workflowService object', () => {
    it('exports all functions as a service object', () => {
      expect(workflowService.getWorkflows).toBe(getWorkflows);
      expect(workflowService.getWorkflow).toBe(getWorkflow);
      expect(workflowService.createWorkflow).toBe(createWorkflow);
      expect(workflowService.updateWorkflow).toBe(updateWorkflow);
      expect(workflowService.renameWorkflow).toBe(renameWorkflow);
      expect(workflowService.deleteWorkflow).toBe(deleteWorkflow);
      expect(workflowService.activateWorkflow).toBe(activateWorkflow);
      expect(workflowService.deactivateWorkflow).toBe(deactivateWorkflow);
      expect(workflowService.getTriggers).toBe(getTriggers);
      expect(workflowService.getActions).toBe(getActions);
    });
  });
});
