import { describe, it, expect, vi, beforeEach } from 'vitest';
import { renderHook, waitFor, act } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import React from 'react';

// Mock apiClient
vi.mock('../../api/client', () => ({
  default: {
    get: vi.fn(),
    post: vi.fn(),
    patch: vi.fn(),
    delete: vi.fn(),
  },
}));

import {
  useContractTemplates,
  useContractTemplate,
  useCreateContractTemplate,
  useUpdateContractTemplate,
  useDeleteContractTemplate,
  useDuplicateContractTemplate,
  usePreviewContractTemplate,
  useContracts,
  useContract,
  useCreateContract,
  useSendContract,
  useVoidContract,
  useResendContract,
  usePublicContract,
  useSignContract,
  useExportLegalPackage,
} from '../useContracts';
import apiClient from '../../api/client';

// Create wrapper
const createWrapper = () => {
  const queryClient = new QueryClient({
    defaultOptions: {
      queries: { retry: false },
      mutations: { retry: false },
    },
  });

  return function Wrapper({ children }: { children: React.ReactNode }) {
    return React.createElement(QueryClientProvider, { client: queryClient }, children);
  };
};

describe('useContracts hooks', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  // --- Contract Templates ---

  describe('useContractTemplates', () => {
    it('fetches all contract templates and transforms data', async () => {
      const mockTemplates = [
        {
          id: 1,
          name: 'Service Agreement',
          description: 'Standard service agreement',
          content: '<p>Service terms...</p>',
          scope: 'CUSTOMER',
          status: 'ACTIVE',
          expires_after_days: 30,
          version: 1,
          version_notes: 'Initial version',
          services: [{ id: 10, name: 'Consultation' }],
          created_by: 5,
          created_by_name: 'John Doe',
          created_at: '2024-01-01T00:00:00Z',
          updated_at: '2024-01-02T00:00:00Z',
        },
        {
          id: 2,
          name: 'NDA',
          description: null,
          content: '<p>Confidentiality terms...</p>',
          scope: 'APPOINTMENT',
          status: 'DRAFT',
          expires_after_days: null,
          version: 2,
          version_notes: null,
          services: [],
          created_by: null,
          created_by_name: null,
          created_at: '2024-01-03T00:00:00Z',
          updated_at: '2024-01-04T00:00:00Z',
        },
      ];
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockTemplates });

      const { result } = renderHook(() => useContractTemplates(), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isSuccess).toBe(true);
      });

      expect(apiClient.get).toHaveBeenCalledWith('/contracts/templates/', { params: {} });
      expect(result.current.data).toHaveLength(2);
      expect(result.current.data?.[0]).toEqual({
        id: '1',
        name: 'Service Agreement',
        description: 'Standard service agreement',
        content: '<p>Service terms...</p>',
        scope: 'CUSTOMER',
        status: 'ACTIVE',
        expires_after_days: 30,
        version: 1,
        version_notes: 'Initial version',
        services: [{ id: 10, name: 'Consultation' }],
        created_by: '5',
        created_by_name: 'John Doe',
        created_at: '2024-01-01T00:00:00Z',
        updated_at: '2024-01-02T00:00:00Z',
      });
      expect(result.current.data?.[1]).toEqual({
        id: '2',
        name: 'NDA',
        description: '',
        content: '<p>Confidentiality terms...</p>',
        scope: 'APPOINTMENT',
        status: 'DRAFT',
        expires_after_days: null,
        version: 2,
        version_notes: '',
        services: [],
        created_by: null,
        created_by_name: null,
        created_at: '2024-01-03T00:00:00Z',
        updated_at: '2024-01-04T00:00:00Z',
      });
    });

    it('applies status filter', async () => {
      vi.mocked(apiClient.get).mockResolvedValue({ data: [] });

      renderHook(() => useContractTemplates('ACTIVE'), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(apiClient.get).toHaveBeenCalledWith('/contracts/templates/', {
          params: { status: 'ACTIVE' },
        });
      });
    });

    it('fetches without filter when status is undefined', async () => {
      vi.mocked(apiClient.get).mockResolvedValue({ data: [] });

      renderHook(() => useContractTemplates(undefined), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(apiClient.get).toHaveBeenCalledWith('/contracts/templates/', { params: {} });
      });
    });
  });

  describe('useContractTemplate', () => {
    it('fetches single contract template by id', async () => {
      const mockTemplate = {
        id: 1,
        name: 'Service Agreement',
        description: 'Standard service agreement',
        content: '<p>Service terms...</p>',
        scope: 'CUSTOMER',
        status: 'ACTIVE',
        expires_after_days: 30,
        version: 1,
        version_notes: 'Initial version',
        services: [{ id: 10, name: 'Consultation' }],
        created_by: 5,
        created_by_name: 'John Doe',
        created_at: '2024-01-01T00:00:00Z',
        updated_at: '2024-01-02T00:00:00Z',
      };
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockTemplate });

      const { result } = renderHook(() => useContractTemplate('1'), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isSuccess).toBe(true);
      });

      expect(apiClient.get).toHaveBeenCalledWith('/contracts/templates/1/');
      expect(result.current.data).toEqual({
        id: '1',
        name: 'Service Agreement',
        description: 'Standard service agreement',
        content: '<p>Service terms...</p>',
        scope: 'CUSTOMER',
        status: 'ACTIVE',
        expires_after_days: 30,
        version: 1,
        version_notes: 'Initial version',
        services: [{ id: 10, name: 'Consultation' }],
        created_by: '5',
        created_by_name: 'John Doe',
        created_at: '2024-01-01T00:00:00Z',
        updated_at: '2024-01-02T00:00:00Z',
      });
    });

    it('does not fetch when id is empty', async () => {
      const { result } = renderHook(() => useContractTemplate(''), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isLoading).toBe(false);
      });

      expect(apiClient.get).not.toHaveBeenCalled();
    });

    it('handles null values in optional fields', async () => {
      const mockTemplate = {
        id: 2,
        name: 'NDA',
        description: null,
        content: '<p>NDA content</p>',
        scope: 'APPOINTMENT',
        status: 'DRAFT',
        expires_after_days: null,
        version: 1,
        version_notes: null,
        services: null,
        created_by: null,
        created_by_name: null,
        created_at: '2024-01-01T00:00:00Z',
        updated_at: '2024-01-01T00:00:00Z',
      };
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockTemplate });

      const { result } = renderHook(() => useContractTemplate('2'), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isSuccess).toBe(true);
      });

      expect(result.current.data?.description).toBe('');
      expect(result.current.data?.version_notes).toBe('');
      expect(result.current.data?.services).toEqual([]);
      expect(result.current.data?.created_by).toBeNull();
      expect(result.current.data?.created_by_name).toBeNull();
    });
  });

  describe('useCreateContractTemplate', () => {
    it('creates contract template', async () => {
      vi.mocked(apiClient.post).mockResolvedValue({ data: { id: 1 } });

      const { result } = renderHook(() => useCreateContractTemplate(), {
        wrapper: createWrapper(),
      });

      await act(async () => {
        await result.current.mutateAsync({
          name: 'New Template',
          content: '<p>Template content</p>',
          scope: 'CUSTOMER',
          description: 'Test description',
          status: 'DRAFT',
          expires_after_days: 30,
          version_notes: 'Initial draft',
          services: ['1', '2'],
        });
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/templates/', {
        name: 'New Template',
        content: '<p>Template content</p>',
        scope: 'CUSTOMER',
        description: 'Test description',
        status: 'DRAFT',
        expires_after_days: 30,
        version_notes: 'Initial draft',
        services: ['1', '2'],
      });
    });

    it('creates template with minimal required fields', async () => {
      vi.mocked(apiClient.post).mockResolvedValue({ data: { id: 1 } });

      const { result } = renderHook(() => useCreateContractTemplate(), {
        wrapper: createWrapper(),
      });

      await act(async () => {
        await result.current.mutateAsync({
          name: 'Minimal Template',
          content: '<p>Content</p>',
          scope: 'APPOINTMENT',
        });
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/templates/', {
        name: 'Minimal Template',
        content: '<p>Content</p>',
        scope: 'APPOINTMENT',
      });
    });
  });

  describe('useUpdateContractTemplate', () => {
    it('updates contract template with partial data', async () => {
      vi.mocked(apiClient.patch).mockResolvedValue({ data: { id: 1 } });

      const { result } = renderHook(() => useUpdateContractTemplate(), {
        wrapper: createWrapper(),
      });

      await act(async () => {
        await result.current.mutateAsync({
          id: '1',
          updates: {
            name: 'Updated Template',
            status: 'ACTIVE',
          },
        });
      });

      expect(apiClient.patch).toHaveBeenCalledWith('/contracts/templates/1/', {
        name: 'Updated Template',
        status: 'ACTIVE',
      });
    });

    it('updates single field', async () => {
      vi.mocked(apiClient.patch).mockResolvedValue({ data: {} });

      const { result } = renderHook(() => useUpdateContractTemplate(), {
        wrapper: createWrapper(),
      });

      await act(async () => {
        await result.current.mutateAsync({
          id: '1',
          updates: { expires_after_days: null },
        });
      });

      expect(apiClient.patch).toHaveBeenCalledWith('/contracts/templates/1/', {
        expires_after_days: null,
      });
    });
  });

  describe('useDeleteContractTemplate', () => {
    it('deletes contract template by id', async () => {
      vi.mocked(apiClient.delete).mockResolvedValue({});

      const { result } = renderHook(() => useDeleteContractTemplate(), {
        wrapper: createWrapper(),
      });

      await act(async () => {
        await result.current.mutateAsync('5');
      });

      expect(apiClient.delete).toHaveBeenCalledWith('/contracts/templates/5/');
    });
  });

  describe('useDuplicateContractTemplate', () => {
    it('duplicates contract template', async () => {
      const mockDuplicate = { id: 2, name: 'Service Agreement (Copy)' };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockDuplicate });

      const { result } = renderHook(() => useDuplicateContractTemplate(), {
        wrapper: createWrapper(),
      });

      let responseData;
      await act(async () => {
        responseData = await result.current.mutateAsync('1');
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/templates/1/duplicate/');
      expect(responseData).toEqual(mockDuplicate);
    });
  });

  describe('usePreviewContractTemplate', () => {
    it('previews contract template with context', async () => {
      const mockPreview = { html: '<p>Preview with John Doe</p>' };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockPreview });

      const { result } = renderHook(() => usePreviewContractTemplate(), {
        wrapper: createWrapper(),
      });

      let responseData;
      await act(async () => {
        responseData = await result.current.mutateAsync({
          id: '1',
          context: { customer_name: 'John Doe', service: 'Consultation' },
        });
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/templates/1/preview/', {
        customer_name: 'John Doe',
        service: 'Consultation',
      });
      expect(responseData).toEqual(mockPreview);
    });

    it('previews template without context', async () => {
      const mockPreview = { html: '<p>Default preview</p>' };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockPreview });

      const { result } = renderHook(() => usePreviewContractTemplate(), {
        wrapper: createWrapper(),
      });

      await act(async () => {
        await result.current.mutateAsync({ id: '1' });
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/templates/1/preview/', {});
    });
  });

  // --- Contracts ---

  describe('useContracts', () => {
    it('fetches all contracts and transforms data', async () => {
      const mockContracts = [
        {
          id: 1,
          template: 10,
          template_name: 'Service Agreement',
          template_version: 1,
          scope: 'CUSTOMER',
          status: 'SIGNED',
          content_html: '<p>Contract content</p>',
          customer: 5,
          customer_name: 'John Doe',
          customer_email: 'john@example.com',
          appointment: 20,
          appointment_service_name: 'Consultation',
          appointment_start_time: '2024-01-15T10:00:00Z',
          service: 30,
          service_name: 'Consultation Service',
          sent_at: '2024-01-10T00:00:00Z',
          signed_at: '2024-01-11T00:00:00Z',
          expires_at: '2024-02-10T00:00:00Z',
          voided_at: null,
          voided_reason: null,
          signing_token: 'abc123',
          created_at: '2024-01-10T00:00:00Z',
          updated_at: '2024-01-11T00:00:00Z',
        },
        {
          id: 2,
          template: 11,
          template_name: 'NDA',
          template_version: 2,
          scope: 'APPOINTMENT',
          status: 'PENDING',
          content: '<p>NDA content</p>',
          customer: null,
          customer_name: null,
          customer_email: null,
          appointment: null,
          appointment_service_name: null,
          appointment_start_time: null,
          service: null,
          service_name: null,
          sent_at: null,
          signed_at: null,
          expires_at: null,
          voided_at: null,
          voided_reason: null,
          public_token: 'xyz789',
          created_at: '2024-01-12T00:00:00Z',
          updated_at: '2024-01-12T00:00:00Z',
        },
      ];
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockContracts });

      const { result } = renderHook(() => useContracts(), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isSuccess).toBe(true);
      });

      expect(apiClient.get).toHaveBeenCalledWith('/contracts/', { params: undefined });
      expect(result.current.data).toHaveLength(2);
      expect(result.current.data?.[0]).toEqual({
        id: '1',
        template: '10',
        template_name: 'Service Agreement',
        template_version: 1,
        scope: 'CUSTOMER',
        status: 'SIGNED',
        content: '<p>Contract content</p>',
        customer: '5',
        customer_name: 'John Doe',
        customer_email: 'john@example.com',
        appointment: '20',
        appointment_service_name: 'Consultation',
        appointment_start_time: '2024-01-15T10:00:00Z',
        service: '30',
        service_name: 'Consultation Service',
        sent_at: '2024-01-10T00:00:00Z',
        signed_at: '2024-01-11T00:00:00Z',
        expires_at: '2024-02-10T00:00:00Z',
        voided_at: null,
        voided_reason: null,
        public_token: 'abc123',
        created_at: '2024-01-10T00:00:00Z',
        updated_at: '2024-01-11T00:00:00Z',
      });
    });

    it('applies filters', async () => {
      vi.mocked(apiClient.get).mockResolvedValue({ data: [] });

      renderHook(
        () =>
          useContracts({
            status: 'SIGNED',
            customer: '5',
            appointment: '20',
          }),
        {
          wrapper: createWrapper(),
        }
      );

      await waitFor(() => {
        expect(apiClient.get).toHaveBeenCalledWith('/contracts/', {
          params: {
            status: 'SIGNED',
            customer: '5',
            appointment: '20',
          },
        });
      });
    });

    it('prefers content_html over content field', async () => {
      const mockContracts = [
        {
          id: 1,
          template: 10,
          template_name: 'Agreement',
          template_version: 1,
          scope: 'CUSTOMER',
          status: 'PENDING',
          content: '<p>Fallback content</p>',
          content_html: '<p>Rendered HTML content</p>',
          signing_token: 'token123',
          created_at: '2024-01-10T00:00:00Z',
          updated_at: '2024-01-10T00:00:00Z',
        },
      ];
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockContracts });

      const { result } = renderHook(() => useContracts(), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isSuccess).toBe(true);
      });

      expect(result.current.data?.[0].content).toBe('<p>Rendered HTML content</p>');
    });

    it('uses signing_token as public_token', async () => {
      const mockContracts = [
        {
          id: 1,
          template: 10,
          template_name: 'Agreement',
          template_version: 1,
          scope: 'CUSTOMER',
          status: 'PENDING',
          content: '<p>Content</p>',
          signing_token: 'secret-token',
          created_at: '2024-01-10T00:00:00Z',
          updated_at: '2024-01-10T00:00:00Z',
        },
      ];
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockContracts });

      const { result } = renderHook(() => useContracts(), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isSuccess).toBe(true);
      });

      expect(result.current.data?.[0].public_token).toBe('secret-token');
    });
  });

  describe('useContract', () => {
    it('fetches single contract by id', async () => {
      const mockContract = {
        id: 1,
        template: 10,
        template_name: 'Service Agreement',
        template_version: 1,
        scope: 'CUSTOMER',
        status: 'SIGNED',
        content: '<p>Contract content</p>',
        customer: 5,
        customer_name: 'John Doe',
        customer_email: 'john@example.com',
        appointment: 20,
        appointment_service_name: 'Consultation',
        appointment_start_time: '2024-01-15T10:00:00Z',
        service: 30,
        service_name: 'Consultation Service',
        sent_at: '2024-01-10T00:00:00Z',
        signed_at: '2024-01-11T00:00:00Z',
        expires_at: '2024-02-10T00:00:00Z',
        voided_at: null,
        voided_reason: null,
        signing_token: 'abc123',
        created_at: '2024-01-10T00:00:00Z',
        updated_at: '2024-01-11T00:00:00Z',
      };
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockContract });

      const { result } = renderHook(() => useContract('1'), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isSuccess).toBe(true);
      });

      expect(apiClient.get).toHaveBeenCalledWith('/contracts/1/');
      expect(result.current.data).toEqual({
        id: '1',
        template: '10',
        template_name: 'Service Agreement',
        template_version: 1,
        scope: 'CUSTOMER',
        status: 'SIGNED',
        content: '<p>Contract content</p>',
        customer: '5',
        customer_name: 'John Doe',
        customer_email: 'john@example.com',
        appointment: '20',
        appointment_service_name: 'Consultation',
        appointment_start_time: '2024-01-15T10:00:00Z',
        service: '30',
        service_name: 'Consultation Service',
        sent_at: '2024-01-10T00:00:00Z',
        signed_at: '2024-01-11T00:00:00Z',
        expires_at: '2024-02-10T00:00:00Z',
        voided_at: null,
        voided_reason: null,
        public_token: 'abc123',
        created_at: '2024-01-10T00:00:00Z',
        updated_at: '2024-01-11T00:00:00Z',
      });
    });

    it('does not fetch when id is empty', async () => {
      const { result } = renderHook(() => useContract(''), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isLoading).toBe(false);
      });

      expect(apiClient.get).not.toHaveBeenCalled();
    });

    it('handles optional fields being null or undefined', async () => {
      const mockContract = {
        id: 2,
        template: 11,
        template_name: 'NDA',
        template_version: 1,
        scope: 'APPOINTMENT',
        status: 'PENDING',
        content: '<p>NDA content</p>',
        customer: null,
        customer_name: null,
        customer_email: null,
        appointment: null,
        appointment_service_name: null,
        appointment_start_time: null,
        service: null,
        service_name: null,
        sent_at: null,
        signed_at: null,
        expires_at: null,
        voided_at: null,
        voided_reason: null,
        public_token: 'token123',
        created_at: '2024-01-10T00:00:00Z',
        updated_at: '2024-01-10T00:00:00Z',
      };
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockContract });

      const { result } = renderHook(() => useContract('2'), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isSuccess).toBe(true);
      });

      expect(result.current.data?.customer).toBeUndefined();
      expect(result.current.data?.customer_name).toBeUndefined();
      expect(result.current.data?.appointment).toBeUndefined();
      expect(result.current.data?.service).toBeUndefined();
    });
  });

  describe('useCreateContract', () => {
    it('creates contract with all fields', async () => {
      vi.mocked(apiClient.post).mockResolvedValue({ data: { id: 1 } });

      const { result } = renderHook(() => useCreateContract(), {
        wrapper: createWrapper(),
      });

      await act(async () => {
        await result.current.mutateAsync({
          template: '10',
          customer_id: '5',
          event_id: '20',
          send_email: true,
        });
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/', {
        template: '10',
        customer_id: '5',
        event_id: '20',
        send_email: true,
      });
    });

    it('creates contract with minimal fields', async () => {
      vi.mocked(apiClient.post).mockResolvedValue({ data: { id: 1 } });

      const { result } = renderHook(() => useCreateContract(), {
        wrapper: createWrapper(),
      });

      await act(async () => {
        await result.current.mutateAsync({
          template: '10',
        });
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/', {
        template: '10',
      });
    });
  });

  describe('useSendContract', () => {
    it('sends contract by id', async () => {
      const mockResponse = { status: 'sent', sent_at: '2024-01-10T00:00:00Z' };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });

      const { result } = renderHook(() => useSendContract(), {
        wrapper: createWrapper(),
      });

      let responseData;
      await act(async () => {
        responseData = await result.current.mutateAsync('1');
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/1/send/');
      expect(responseData).toEqual(mockResponse);
    });
  });

  describe('useVoidContract', () => {
    it('voids contract with reason', async () => {
      const mockResponse = { status: 'voided' };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });

      const { result } = renderHook(() => useVoidContract(), {
        wrapper: createWrapper(),
      });

      let responseData;
      await act(async () => {
        responseData = await result.current.mutateAsync({
          id: '1',
          reason: 'Customer requested cancellation',
        });
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/1/void/', {
        reason: 'Customer requested cancellation',
      });
      expect(responseData).toEqual(mockResponse);
    });
  });

  describe('useResendContract', () => {
    it('resends contract by id', async () => {
      const mockResponse = { status: 'sent' };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });

      const { result } = renderHook(() => useResendContract(), {
        wrapper: createWrapper(),
      });

      let responseData;
      await act(async () => {
        responseData = await result.current.mutateAsync('1');
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/1/resend/');
      expect(responseData).toEqual(mockResponse);
    });
  });

  // --- Public Contract Access ---

  describe('usePublicContract', () => {
    it('fetches public contract view by token', async () => {
      const mockPublicView = {
        contract: {
          id: '1',
          content: '<p>Contract content</p>',
          status: 'PENDING',
        },
        template: {
          name: 'Service Agreement',
          content: '<p>Template content</p>',
        },
        business: {
          name: 'Acme Corp',
          logo_url: 'https://example.com/logo.png',
        },
        customer: {
          name: 'John Doe',
          email: 'john@example.com',
        },
      };
      vi.mocked(apiClient.get).mockResolvedValue({ data: mockPublicView });

      const { result } = renderHook(() => usePublicContract('abc123'), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isSuccess).toBe(true);
      });

      expect(apiClient.get).toHaveBeenCalledWith('/contracts/sign/abc123/');
      expect(result.current.data).toEqual(mockPublicView);
    });

    it('does not fetch when token is empty', async () => {
      const { result } = renderHook(() => usePublicContract(''), {
        wrapper: createWrapper(),
      });

      await waitFor(() => {
        expect(result.current.isLoading).toBe(false);
      });

      expect(apiClient.get).not.toHaveBeenCalled();
    });
  });

  describe('useSignContract', () => {
    it('signs contract with all required fields', async () => {
      const mockResponse = { status: 'signed', signed_at: '2024-01-10T00:00:00Z' };
      vi.mocked(apiClient.post).mockResolvedValue({ data: mockResponse });

      const { result } = renderHook(() => useSignContract(), {
        wrapper: createWrapper(),
      });

      let responseData;
      await act(async () => {
        responseData = await result.current.mutateAsync({
          token: 'abc123',
          signer_name: 'John Doe',
          consent_checkbox_checked: true,
          electronic_consent_given: true,
        });
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/sign/abc123/', {
        signer_name: 'John Doe',
        consent_checkbox_checked: true,
        electronic_consent_given: true,
      });
      expect(responseData).toEqual(mockResponse);
    });

    it('handles signing with consent checkboxes false', async () => {
      vi.mocked(apiClient.post).mockResolvedValue({ data: {} });

      const { result } = renderHook(() => useSignContract(), {
        wrapper: createWrapper(),
      });

      await act(async () => {
        await result.current.mutateAsync({
          token: 'abc123',
          signer_name: 'Jane Smith',
          consent_checkbox_checked: false,
          electronic_consent_given: false,
        });
      });

      expect(apiClient.post).toHaveBeenCalledWith('/contracts/sign/abc123/', {
        signer_name: 'Jane Smith',
        consent_checkbox_checked: false,
        electronic_consent_given: false,
      });
    });
  });

  describe('useExportLegalPackage', () => {
    it('calls API with correct parameters and triggers download', async () => {
      // Mock blob response
      const mockBlob = new Blob(['mock zip content'], { type: 'application/zip' });
      const mockResponse = {
        data: mockBlob,
        headers: {
          'content-disposition': 'attachment; filename="legal_export_contract_1.zip"',
        },
      };
      vi.mocked(apiClient.get).mockResolvedValue(mockResponse);

      // Mock DOM methods
      const mockClick = vi.fn();
      const mockRemove = vi.fn();
      const mockSetAttribute = vi.fn();

      // Create a real anchor element and spy on it
      const mockLink = document.createElement('a');
      vi.spyOn(mockLink, 'click').mockImplementation(mockClick);
      vi.spyOn(mockLink, 'remove').mockImplementation(mockRemove);
      vi.spyOn(mockLink, 'setAttribute').mockImplementation(mockSetAttribute);

      const mockCreateObjectURL = vi.fn().mockReturnValue('blob:mock-url');
      const mockRevokeObjectURL = vi.fn();

      // Store originals
      const origCreateObjectURL = global.URL.createObjectURL;
      const origRevokeObjectURL = global.URL.revokeObjectURL;

      // Setup mocks
      global.URL.createObjectURL = mockCreateObjectURL;
      global.URL.revokeObjectURL = mockRevokeObjectURL;

      // Spy on createElement but return mockLink only for 'a' tags
      const originalCreateElement = document.createElement.bind(document);
      const createElementSpy = vi.spyOn(document, 'createElement');
      createElementSpy.mockImplementation((tagName: string) => {
        if (tagName === 'a') return mockLink;
        return originalCreateElement(tagName as any);
      });

      const { result } = renderHook(() => useExportLegalPackage(), {
        wrapper: createWrapper(),
      });

      let responseData;
      await act(async () => {
        responseData = await result.current.mutateAsync('1');
      });

      expect(apiClient.get).toHaveBeenCalledWith('/contracts/1/export_legal/', {
        responseType: 'blob',
      });
      expect(mockCreateObjectURL).toHaveBeenCalledWith(expect.any(Blob));
      expect(mockClick).toHaveBeenCalled();
      expect(mockRemove).toHaveBeenCalled();
      expect(mockRevokeObjectURL).toHaveBeenCalledWith('blob:mock-url');
      expect(responseData).toEqual({ success: true });

      // Cleanup
      global.URL.createObjectURL = origCreateObjectURL;
      global.URL.revokeObjectURL = origRevokeObjectURL;
      createElementSpy.mockRestore();
    });
  });
});
