import { describe, it, expect, vi, beforeEach } from 'vitest';

// Mock the API client
const mockApiGet = vi.fn();
const mockApiPost = vi.fn();
const mockApiPatch = vi.fn();
const mockApiDelete = vi.fn();

vi.mock('@/api/client', () => ({
  apiGet: (...args: any[]) => mockApiGet(...args),
  apiPost: (...args: any[]) => mockApiPost(...args),
  apiPatch: (...args: any[]) => mockApiPatch(...args),
  apiDelete: (...args: any[]) => mockApiDelete(...args),
}));

// Mock react-query
vi.mock('@tanstack/react-query', () => ({
  useQueryClient: () => ({
    invalidateQueries: vi.fn(),
  }),
  useQuery: vi.fn(),
  useMutation: vi.fn(({ mutationFn, onSuccess }) => ({
    mutateAsync: async (args: any) => {
      const result = await mutationFn(args);
      if (onSuccess) onSuccess(result, args);
      return result;
    },
    isPending: false,
  })),
}));

describe('Workflow API Hooks', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('useWorkflows', () => {
    it('calls apiGet with correct endpoint', async () => {
      const { useWorkflows } = await import('../workflows');
      const { useQuery } = await import('@tanstack/react-query');

      (useQuery as any).mockImplementation(({ queryKey, queryFn }: any) => {
        expect(queryKey[0]).toBe('workflows');
        queryFn();
        return { data: undefined, isLoading: false };
      });

      useWorkflows();
      expect(mockApiGet).toHaveBeenCalledWith(
        expect.stringContaining('/workflows?')
      );
    });

    it('passes is_active filter when provided', async () => {
      const { useWorkflows } = await import('../workflows');
      const { useQuery } = await import('@tanstack/react-query');

      (useQuery as any).mockImplementation(({ queryFn }: any) => {
        queryFn();
        return { data: undefined, isLoading: false };
      });

      useWorkflows(1, 20, true);
      expect(mockApiGet).toHaveBeenCalledWith(
        expect.stringContaining('is_active=true')
      );
    });
  });

  describe('useWorkflow', () => {
    it('calls apiGet with correct endpoint', async () => {
      const { useWorkflow } = await import('../workflows');
      const { useQuery } = await import('@tanstack/react-query');

      (useQuery as any).mockImplementation(({ queryKey, queryFn, enabled }: any) => {
        expect(queryKey).toEqual(['workflows', 'wf-123']);
        expect(enabled).toBe(true);
        queryFn();
        return { data: undefined, isLoading: false };
      });

      useWorkflow('wf-123');
      expect(mockApiGet).toHaveBeenCalledWith('/workflows/wf-123');
    });

    it('is disabled when id is undefined', async () => {
      const { useWorkflow } = await import('../workflows');
      const { useQuery } = await import('@tanstack/react-query');

      (useQuery as any).mockImplementation(({ enabled }: any) => {
        expect(enabled).toBe(false);
        return { data: undefined, isLoading: false };
      });

      useWorkflow(undefined);
      expect(mockApiGet).not.toHaveBeenCalled();
    });
  });

  describe('useCreateWorkflow', () => {
    it('calls apiPost with correct endpoint and data', async () => {
      const { useCreateWorkflow } = await import('../workflows');
      const { useMutation } = await import('@tanstack/react-query');

      (useMutation as any).mockImplementation(({ mutationFn, onSuccess }: any) => ({
        mutateAsync: async (args: any) => {
          const result = await mutationFn(args);
          if (onSuccess) onSuccess(result, args);
          return result;
        },
        isPending: false,
      }));

      const { mutateAsync } = useCreateWorkflow();
      const payload = {
        name: 'Test WF',
        steps: [{ name: 'S1', type: 'action' as const, config: {} }],
      };
      mockApiPost.mockResolvedValue({ id: 'wf-1', ...payload });
      await mutateAsync(payload);
      expect(mockApiPost).toHaveBeenCalledWith('/workflows', payload);
    });
  });

  describe('useUpdateWorkflow', () => {
    it('calls apiPatch with correct endpoint and data', async () => {
      const { useUpdateWorkflow } = await import('../workflows');
      const { useMutation } = await import('@tanstack/react-query');

      (useMutation as any).mockImplementation(({ mutationFn, onSuccess }: any) => ({
        mutateAsync: async (args: any) => {
          const result = await mutationFn(args);
          if (onSuccess) onSuccess(result, args);
          return result;
        },
        isPending: false,
      }));

      const { mutateAsync } = useUpdateWorkflow();
      const payload = { id: 'wf-1', data: { name: 'Updated' } };
      mockApiPatch.mockResolvedValue({ id: 'wf-1', name: 'Updated' });
      await mutateAsync(payload);
      expect(mockApiPatch).toHaveBeenCalledWith('/workflows/wf-1', {
        name: 'Updated',
      });
    });
  });

  describe('useDeleteWorkflow', () => {
    it('calls apiDelete with correct endpoint', async () => {
      const { useDeleteWorkflow } = await import('../workflows');
      const { useMutation } = await import('@tanstack/react-query');

      (useMutation as any).mockImplementation(({ mutationFn, onSuccess }: any) => ({
        mutateAsync: async (args: any) => {
          const result = await mutationFn(args);
          if (onSuccess) onSuccess(result, args);
          return result;
        },
        isPending: false,
      }));

      const { mutateAsync } = useDeleteWorkflow();
      mockApiDelete.mockResolvedValue(undefined);
      await mutateAsync('wf-1');
      expect(mockApiDelete).toHaveBeenCalledWith('/workflows/wf-1');
    });
  });

  describe('useWorkflowInstances', () => {
    it('calls apiGet with instances endpoint', async () => {
      const { useWorkflowInstances } = await import('../workflows');
      const { useQuery } = await import('@tanstack/react-query');

      (useQuery as any).mockImplementation(({ queryFn }: any) => {
        queryFn();
        return { data: undefined, isLoading: false };
      });

      useWorkflowInstances();
      expect(mockApiGet).toHaveBeenCalledWith(
        expect.stringContaining('/workflows/instances?')
      );
    });

    it('passes status filter when provided', async () => {
      const { useWorkflowInstances } = await import('../workflows');
      const { useQuery } = await import('@tanstack/react-query');

      (useQuery as any).mockImplementation(({ queryFn }: any) => {
        queryFn();
        return { data: undefined, isLoading: false };
      });

      useWorkflowInstances(1, 20, 'completed');
      expect(mockApiGet).toHaveBeenCalledWith(
        expect.stringContaining('status=completed')
      );
    });
  });

  describe('useWorkflowInstance', () => {
    it('calls apiGet with instance detail endpoint', async () => {
      const { useWorkflowInstance } = await import('../workflows');
      const { useQuery } = await import('@tanstack/react-query');

      (useQuery as any).mockImplementation(({ queryFn, enabled }: any) => {
        expect(enabled).toBe(true);
        queryFn();
        return { data: undefined, isLoading: false };
      });

      useWorkflowInstance('inst-1');
      expect(mockApiGet).toHaveBeenCalledWith(
        '/workflows/instances/inst-1'
      );
    });
  });

  describe('useCreateWorkflowInstance', () => {
    it('calls apiPost with correct endpoint and data', async () => {
      const { useCreateWorkflowInstance } = await import('../workflows');
      const { useMutation } = await import('@tanstack/react-query');

      (useMutation as any).mockImplementation(({ mutationFn, onSuccess }: any) => ({
        mutateAsync: async (args: any) => {
          const result = await mutationFn(args);
          if (onSuccess) onSuccess(result, args);
          return result;
        },
        isPending: false,
      }));

      const { mutateAsync } = useCreateWorkflowInstance();
      const payload = {
        workflowId: 'wf-1',
        data: { context: { foo: 'bar' } },
      };
      mockApiPost.mockResolvedValue({ id: 'inst-1' });
      await mutateAsync(payload);
      expect(mockApiPost).toHaveBeenCalledWith(
        '/workflows/wf-1/instances',
        { context: { foo: 'bar' } }
      );
    });
  });

  describe('useAdvanceWorkflowInstance', () => {
    it('calls apiPost with advance endpoint and decision', async () => {
      const { useAdvanceWorkflowInstance } = await import('../workflows');
      const { useMutation } = await import('@tanstack/react-query');

      (useMutation as any).mockImplementation(({ mutationFn, onSuccess }: any) => ({
        mutateAsync: async (args: any) => {
          const result = await mutationFn(args);
          if (onSuccess) onSuccess(result, args);
          return result;
        },
        isPending: false,
      }));

      const { mutateAsync } = useAdvanceWorkflowInstance();
      const payload = {
        instanceId: 'inst-1',
        data: { decision: 'approve' as const, comment: 'LGTM' },
      };
      mockApiPost.mockResolvedValue({ id: 'inst-1', status: 'in_progress' });
      await mutateAsync(payload);
      expect(mockApiPost).toHaveBeenCalledWith(
        '/workflows/instances/inst-1/advance',
        { decision: 'approve', comment: 'LGTM' }
      );
    });
  });

  describe('useCancelWorkflowInstance', () => {
    it('calls apiPost with cancel endpoint', async () => {
      const { useCancelWorkflowInstance } = await import('../workflows');
      const { useMutation } = await import('@tanstack/react-query');

      (useMutation as any).mockImplementation(({ mutationFn, onSuccess }: any) => ({
        mutateAsync: async (args: any) => {
          const result = await mutationFn(args);
          if (onSuccess) onSuccess(result, args);
          return result;
        },
        isPending: false,
      }));

      const { mutateAsync } = useCancelWorkflowInstance();
      mockApiPost.mockResolvedValue({ id: 'inst-1', status: 'cancelled' });
      await mutateAsync('inst-1');
      expect(mockApiPost).toHaveBeenCalledWith(
        '/workflows/instances/inst-1/cancel'
      );
    });
  });
});
