/**
 * Unit Tests for Analytics Service
 * Tests the analyticsService for proper event tracking and user property management
 */

import { describe, it, expect, beforeEach, vi, afterEach } from 'vitest';
import { analyticsService, AnalyticsEvents, AnalyticsUserProperties } from '../../src/services/analyticsService';

// Mock gtag function
const mockGtag = vi.fn();

// Setup gtag in global window before tests
if (typeof window !== 'undefined') {
  (window as any).gtag = mockGtag;
}

describe('Analytics Service', () => {
  beforeEach(() => {
    vi.clearAllMocks();
    // Re-enable analytics for each test
    analyticsService.setEnabled(true);
  });

  describe('Event Tracking', () => {
    it('should track user signup event', () => {
      analyticsService.trackSignup('frodo_baggins');
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.USER_SIGNUP, {
        username: 'frodo_baggins',
      });
    });

    it('should track user login event', () => {
      analyticsService.trackLogin('gandalf');
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.USER_LOGIN, {
        username: 'gandalf',
      });
    });

    it('should track user logout event', () => {
      analyticsService.trackLogout();
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.USER_LOGOUT, {});
    });

    it('should track quest creation', () => {
      analyticsService.trackQuestCreated(1, 'Find the Ring', 'The Ring');
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.QUEST_CREATED, {
        quest_id: 1,
        quest_title: 'Find the Ring',
        quest_type: 'The Ring',
      });
    });

    it('should track quest completion', () => {
      analyticsService.trackQuestCompleted(5, 'Destroy the Ring', 'Trivia');
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.QUEST_COMPLETED, {
        quest_id: 5,
        quest_title: 'Destroy the Ring',
        game_type: 'Trivia',
      });
    });

    it('should track game completion', () => {
      analyticsService.trackGameCompleted('memory', 95);
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.GAME_COMPLETED, {
        game_type: 'memory',
        score: 95,
      });
    });

    it('should track game failure', () => {
      analyticsService.trackGameFailed('reaction', 'timeout');
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.GAME_FAILED, {
        game_type: 'reaction',
        reason: 'timeout',
      });
    });

    it('should track bargain initiation', () => {
      analyticsService.trackBargainInitiated();
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.BARGAIN_INITIATED, {});
    });

    it('should track successful bargain', () => {
      analyticsService.trackBargainCompleted('Mithril Coat', 500);
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.BARGAIN_COMPLETED, {
        item_name: 'Mithril Coat',
        bargain_value: 500,
      });
    });

    it('should track item purchase', () => {
      analyticsService.trackItemPurchased('Sword of Elendil', 250, 42);
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.ITEM_PURCHASED, {
        item_name: 'Sword of Elendil',
        item_id: 42,
        price: 250,
        currency: 'gold',
      });
    });

    it('should track NPC chat initiation', () => {
      analyticsService.trackNpcChatInitiated('Gandalf');
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.NPC_CHAT_INITIATED, {
        character: 'Gandalf',
      });
    });

    it('should track NPC message sent', () => {
      analyticsService.trackNpcMessageSent('Frodo', 42);
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.NPC_MESSAGE_SENT, {
        character: 'Frodo',
        message_length: 42,
      });
    });

    it('should track inventory viewed', () => {
      analyticsService.trackInventoryViewed(8);
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.INVENTORY_VIEWED, {
        item_count: 8,
      });
    });

    it('should track inventory item added', () => {
      analyticsService.trackInventoryItemAdded('Mithril Coat', 1);
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.INVENTORY_ITEM_ADDED, {
        item_name: 'Mithril Coat',
        quantity: 1,
      });
    });

    it('should track page view', () => {
      analyticsService.trackPageView('/dashboard', 'The Council Chamber');
      
      expect(mockGtag).toHaveBeenCalledWith('event', 'page_view', {
        page_title: 'The Council Chamber',
        page_location: window.location.href,
      });
    });

    it('should track map viewed', () => {
      analyticsService.trackMapViewed();
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.MAP_VIEWED, {
        page_title: 'Middle-earth Map',
      });
    });

    it('should track dashboard viewed', () => {
      analyticsService.trackDashboardViewed();
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.DASHBOARD_VIEWED, {
        page_title: 'The Council Chamber',
      });
    });

    it('should track quests page viewed', () => {
      analyticsService.trackQuestsPageViewed();
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.QUESTS_PAGE_VIEWED, {
        page_title: 'Quests',
      });
    });
  });

  describe('User Properties', () => {
    it('should set user properties', () => {
      analyticsService.setUserProperties({
        character_name: 'Frodo',
        user_type: 'fellowship_member',
      });
      
      expect(mockGtag).toHaveBeenCalledWith('config', {
        character_name: 'Frodo',
        user_type: 'fellowship_member',
      });
    });

    it('should set user ID', () => {
      analyticsService.setUserId(123);
      
      expect(mockGtag).toHaveBeenCalledWith('config', {
        'user_id': '123',
      });
    });
  });

  describe('Analytics Management', () => {
    it('should check if analytics is enabled', () => {
      expect(analyticsService.isAnalyticsEnabled()).toBe(true);
    });

    it('should enable/disable analytics', () => {
      analyticsService.setEnabled(false);
      expect(analyticsService.isAnalyticsEnabled()).toBe(false);
      
      analyticsService.setEnabled(true);
      expect(analyticsService.isAnalyticsEnabled()).toBe(true);
    });
  });

  describe('Default Values', () => {
    it('should handle game completion with default score', () => {
      analyticsService.trackGameCompleted('trivia');
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.GAME_COMPLETED, {
        game_type: 'trivia',
        score: 0,
      });
    });

    it('should handle inventory without item count', () => {
      analyticsService.trackInventoryViewed();
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.INVENTORY_VIEWED, {
        item_count: 0,
      });
    });

    it('should handle quest creation without type', () => {
      analyticsService.trackQuestCreated(1, 'A Quest');
      
      expect(mockGtag).toHaveBeenCalledWith('event', AnalyticsEvents.QUEST_CREATED, {
        quest_id: 1,
        quest_title: 'A Quest',
        quest_type: 'unknown',
      });
    });
  });

  describe('Error Handling', () => {
    it('should handle gtag errors gracefully', () => {
      mockGtag.mockImplementationOnce(() => {
        throw new Error('GTags error');
      });
      
      // Should not throw
      expect(() => {
        analyticsService.trackLogin('user');
      }).not.toThrow();
    });

    it('should log errors to console', () => {
      const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
      
      mockGtag.mockImplementationOnce(() => {
        throw new Error('GTags error');
      });
      
      analyticsService.trackLogin('user');
      
      expect(consoleSpy).toHaveBeenCalledWith(
        'Error tracking analytics event:',
        expect.any(Error)
      );
      
      consoleSpy.mockRestore();
    });
  });
});
