/**
 * useCategorizedItems Hook Tests
 *
 * Tests the categorized items hook including:
 * - Trigger/action conversion to TriggerAction format
 * - Icon mapping
 * - Category derivation
 * - Search filtering
 * - Item categorization (available, notConnected, gated)
 */
import { describe, it, expect } from 'vitest';
import { renderHook } from '@testing-library/react';
import { useCategorizedItems } from './useCategorizedItems';
import { Trigger } from '../types/trigger';
import { Action } from '../types/action';

describe('useCategorizedItems', () => {
  // ==========================================================================
  // Test Data
  // ==========================================================================

  const mockTriggers: Trigger[] = [
    {
      type: 'wordpress/user_registration',
      label: 'User Registration',
      description: 'Triggered when a new user registers',
      available_fields: [],
      is_available: true,
      availability_reason: '',
    },
    {
      type: 'wordpress/post_published',
      label: 'Post Published',
      description: 'Triggered when a post is published',
      available_fields: [],
      is_available: true,
      availability_reason: '',
    },
    {
      type: 'wordpress/comment_added',
      label: 'Comment Added',
      description: 'Triggered when a comment is added',
      available_fields: [],
      is_available: true,
      availability_reason: '',
    },
    {
      type: 'custom/custom_event',
      label: 'Custom Event',
      description: 'A custom event trigger',
      available_fields: [],
      is_available: false,
      availability_reason: 'Pro feature',
      plugin_type: 'paid',
    },
  ];

  const mockActions: Action[] = [
    {
      type: 'wordpress/send_email',
      label: 'Send Email',
      description: 'Sends an email to specified recipients',
      integration: 'wordpress',
      schema: {},
      output_fields: [],
      is_available: true,
      availability_reason: '',
      is_connected: true,
      requires_connection: false,
    },
    {
      type: 'wordpress/create_user',
      label: 'Create User',
      description: 'Creates a new WordPress user',
      integration: 'wordpress',
      schema: {},
      output_fields: [],
      is_available: true,
      availability_reason: '',
      is_connected: true,
      requires_connection: false,
    },
    {
      type: 'mailchimp/add_subscriber',
      label: 'Add Subscriber',
      description: 'Adds a subscriber to Mailchimp',
      integration: 'mailchimp',
      schema: {},
      output_fields: [],
      is_available: true,
      availability_reason: '',
      is_connected: false,
      requires_connection: true,
    },
    {
      type: 'wordpress/pro_action',
      label: 'Pro Action',
      description: 'A premium action',
      integration: 'wordpress',
      schema: {},
      output_fields: [],
      is_available: false,
      availability_reason: 'Requires Pro',
      is_connected: true,
      requires_connection: false,
      plugin_type: 'paid',
    },
  ];

  // ==========================================================================
  // Trigger Conversion Tests
  // ==========================================================================

  describe('trigger conversion', () => {
    it('converts triggers to TriggerAction format', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: '',
        }),
      );

      expect(result.current.items).toHaveLength(4);
      expect(result.current.items[0]).toMatchObject({
        id: 'wordpress/user_registration',
        name: 'User Registration',
        description: 'Triggered when a new user registers',
      });
    });

    it('sets isConnected to true for all triggers', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: '',
        }),
      );

      result.current.items.forEach((item) => {
        expect(item.isConnected).toBe(true);
        expect(item.requiresConnection).toBe(false);
      });
    });

    it('preserves availability information from trigger', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: '',
        }),
      );

      const gatedTrigger = result.current.items.find((i) => i.id === 'custom/custom_event');
      expect(gatedTrigger?.isAvailable).toBe(false);
      expect(gatedTrigger?.availabilityReason).toBe('Pro feature');
      expect(gatedTrigger?.pluginType).toBe('paid');
    });

    it('defaults integration to wordpress for triggers', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: '',
        }),
      );

      expect(result.current.items[0].integration).toBe('wordpress');
    });
  });

  // ==========================================================================
  // Action Conversion Tests
  // ==========================================================================

  describe('action conversion', () => {
    it('converts actions to TriggerAction format', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: mockActions,
          searchQuery: '',
        }),
      );

      expect(result.current.items).toHaveLength(4);
      expect(result.current.items[0]).toMatchObject({
        id: 'wordpress/send_email',
        name: 'Send Email',
        description: 'Sends an email to specified recipients',
      });
    });

    it('preserves connection status from action', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: mockActions,
          searchQuery: '',
        }),
      );

      const mailchimpAction = result.current.items.find((i) => i.id === 'mailchimp/add_subscriber');
      expect(mailchimpAction?.isConnected).toBe(false);
      expect(mailchimpAction?.requiresConnection).toBe(true);
    });

    it('preserves integration from action', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: mockActions,
          searchQuery: '',
        }),
      );

      const mailchimpAction = result.current.items.find((i) => i.id === 'mailchimp/add_subscriber');
      expect(mailchimpAction?.integration).toBe('mailchimp');
    });

    it('defaults integration to wordpress for actions without one', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: mockActions,
          searchQuery: '',
        }),
      );

      expect(result.current.items[0].integration).toBe('wordpress');
    });
  });

  // ==========================================================================
  // Icon Mapping Tests
  // ==========================================================================

  describe('icon mapping', () => {
    it('maps user-related triggers to UserPlus icon', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: '',
        }),
      );

      const userTrigger = result.current.items.find((i) => i.id === 'wordpress/user_registration');
      expect(userTrigger?.icon).toBe('UserPlus');
    });

    it('maps post-related triggers to FileText icon', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: '',
        }),
      );

      const postTrigger = result.current.items.find((i) => i.id === 'wordpress/post_published');
      expect(postTrigger?.icon).toBe('FileText');
    });

    it('maps comment triggers to MessageSquare icon', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: '',
        }),
      );

      const commentTrigger = result.current.items.find((i) => i.id === 'wordpress/comment_added');
      expect(commentTrigger?.icon).toBe('MessageSquare');
    });

    it('maps unknown triggers to Zap icon', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: '',
        }),
      );

      const customTrigger = result.current.items.find((i) => i.id === 'custom/custom_event');
      expect(customTrigger?.icon).toBe('Zap');
    });
  });

  // ==========================================================================
  // Category Derivation Tests
  // ==========================================================================

  describe('category derivation', () => {
    it('categorizes user-related items as WordPress Users', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: '',
        }),
      );

      const userTrigger = result.current.items.find((i) => i.id === 'wordpress/user_registration');
      expect(userTrigger?.category).toBe('WordPress Users');
    });

    it('categorizes post-related items as WordPress Content', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: '',
        }),
      );

      const postTrigger = result.current.items.find((i) => i.id === 'wordpress/post_published');
      expect(postTrigger?.category).toBe('WordPress Content');
    });

    it('categorizes email actions as Email', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: mockActions,
          searchQuery: '',
        }),
      );

      const emailAction = result.current.items.find((i) => i.id === 'wordpress/send_email');
      expect(emailAction?.category).toBe('Email');
    });

    it('categorizes unknown items as General', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: '',
        }),
      );

      const customTrigger = result.current.items.find((i) => i.id === 'custom/custom_event');
      expect(customTrigger?.category).toBe('General');
    });
  });

  // ==========================================================================
  // Search Filtering Tests
  // ==========================================================================

  describe('search filtering', () => {
    it('filters items by name', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: 'user',
        }),
      );

      expect(result.current.filteredItems).toHaveLength(1);
      expect(result.current.filteredItems[0].id).toBe('wordpress/user_registration');
    });

    it('filters items by description', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: 'registers',
        }),
      );

      expect(result.current.filteredItems).toHaveLength(1);
      expect(result.current.filteredItems[0].id).toBe('wordpress/user_registration');
    });

    it('filters items by integration', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: mockActions,
          searchQuery: 'mailchimp',
        }),
      );

      expect(result.current.filteredItems).toHaveLength(1);
      expect(result.current.filteredItems[0].id).toBe('mailchimp/add_subscriber');
    });

    it('performs case-insensitive search', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: mockTriggers,
          actions: [],
          searchQuery: 'USER',
        }),
      );

      expect(result.current.filteredItems).toHaveLength(1);
      expect(result.current.filteredItems[0].id).toBe('wordpress/user_registration');
    });
  });

  // ==========================================================================
  // Item Categorization Tests
  // ==========================================================================

  describe('item categorization', () => {
    it('categorizes available and connected items correctly', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: mockActions,
          searchQuery: '',
        }),
      );

      // send_email and create_user are available and connected
      expect(result.current.availableItems).toHaveLength(2);
      expect(result.current.availableItems.map((i) => i.id)).toContain('wordpress/send_email');
      expect(result.current.availableItems.map((i) => i.id)).toContain('wordpress/create_user');
    });

    it('categorizes not connected items correctly', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: mockActions,
          searchQuery: '',
        }),
      );

      // mailchimp_add_subscriber requires connection but is not connected
      expect(result.current.notConnectedItems).toHaveLength(1);
      expect(result.current.notConnectedItems[0].id).toBe('mailchimp/add_subscriber');
    });

    it('categorizes gated items correctly', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: mockActions,
          searchQuery: '',
        }),
      );

      // pro_action is not available
      expect(result.current.gatedItems).toHaveLength(1);
      expect(result.current.gatedItems[0].id).toBe('wordpress/pro_action');
    });

    it('applies search filter to all categories', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: mockActions,
          searchQuery: 'email',
        }),
      );

      // Only send_email matches
      expect(result.current.filteredItems).toHaveLength(1);
      expect(result.current.availableItems).toHaveLength(1);
      expect(result.current.notConnectedItems).toHaveLength(0);
      expect(result.current.gatedItems).toHaveLength(0);
    });
  });

  // ==========================================================================
  // Edge Cases
  // ==========================================================================

  describe('edge cases', () => {
    it('handles empty triggers array', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: [],
          actions: [],
          searchQuery: '',
        }),
      );

      expect(result.current.items).toHaveLength(0);
      expect(result.current.filteredItems).toHaveLength(0);
    });

    it('handles empty actions array', () => {
      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: [],
          searchQuery: '',
        }),
      );

      expect(result.current.items).toHaveLength(0);
      expect(result.current.filteredItems).toHaveLength(0);
    });

    it('handles missing optional fields in triggers', () => {
      const minimalTrigger: Trigger = {
        type: 'minimal',
        label: 'Minimal',
        description: 'Minimal trigger',
        available_fields: [],
        is_available: true,
        availability_reason: '',
      };

      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'trigger',
          triggers: [minimalTrigger],
          actions: [],
          searchQuery: '',
        }),
      );

      expect(result.current.items[0]).toMatchObject({
        id: 'minimal',
        isAvailable: true,
        pluginType: '',
        installUrl: '',
      });
    });

    it('handles missing optional fields in actions', () => {
      const minimalAction: Action = {
        type: 'minimal',
        label: 'Minimal',
        description: 'Minimal action',
        integration: 'wordpress',
        schema: {},
        output_fields: [],
        is_available: true,
        availability_reason: '',
        is_connected: true,
        requires_connection: false,
      };

      const { result } = renderHook(() =>
        useCategorizedItems({
          type: 'action',
          triggers: [],
          actions: [minimalAction],
          searchQuery: '',
        }),
      );

      expect(result.current.items[0]).toMatchObject({
        id: 'minimal',
        isAvailable: true,
        isConnected: true,
        requiresConnection: false,
      });
    });
  });

  // ==========================================================================
  // Memoization Tests
  // ==========================================================================

  describe('memoization', () => {
    it('recalculates filteredItems when search query changes', () => {
      const { result, rerender } = renderHook(
        ({ searchQuery }) =>
          useCategorizedItems({
            type: 'trigger',
            triggers: mockTriggers,
            actions: [],
            searchQuery,
          }),
        { initialProps: { searchQuery: '' } },
      );

      // All items with empty search
      expect(result.current.filteredItems).toHaveLength(4);

      // Rerender with search query
      rerender({ searchQuery: 'user' });

      // Should now be filtered
      expect(result.current.filteredItems).toHaveLength(1);
      expect(result.current.filteredItems[0].id).toBe('wordpress/user_registration');
    });

    it('recalculates when type changes', () => {
      const { result, rerender } = renderHook(
        ({ type }: { type: 'trigger' | 'action' }) =>
          useCategorizedItems({
            type,
            triggers: mockTriggers,
            actions: mockActions,
            searchQuery: '',
          }),
        { initialProps: { type: 'trigger' as 'trigger' | 'action' } },
      );

      expect(result.current.items).toHaveLength(4);

      rerender({ type: 'action' });

      expect(result.current.items).toHaveLength(4);
      expect(result.current.items[0].id).toBe('wordpress/send_email');
    });
  });
});
