/**
 * Tests that new event dispatch points properly call queueRealtimeNotification
 */
import { describe, it, expect, beforeEach, vi } from 'vitest';

// Use vi.hoisted so the mock fn is available when vi.mock factories run (they are hoisted)
const { mockQueueRealtimeNotification } = vi.hoisted(() => ({
  mockQueueRealtimeNotification: vi.fn().mockResolvedValue({ sent: true }),
}));

// Mock the notification manager
vi.mock('../../../src/services/notifications/notificationManager.js', () => ({
  queueRealtimeNotification: mockQueueRealtimeNotification,
  notifyRealtimeEvent: vi.fn().mockResolvedValue({ sent: true }),
  clearThrottle: vi.fn(),
}));

// Mock push service (required by notificationManager)
vi.mock('../../../src/services/notifications/pushNotificationService.js', () => ({
  sendPushNotification: vi.fn().mockResolvedValue({ success: true }),
}));

// Mock database (required by retention modules)
vi.mock('../../../src/database/index.js', () => ({
  query: vi.fn().mockResolvedValue([]),
  queryOne: vi.fn().mockResolvedValue(null),
  execute: vi.fn().mockResolvedValue({ affectedRows: 0 }),
  getConnection: vi.fn().mockResolvedValue({
    query: vi.fn(),
    release: vi.fn(),
    beginTransaction: vi.fn(),
    commit: vi.fn(),
    rollback: vi.fn(),
  }),
  transaction: vi.fn(),
  getPool: vi.fn(),
  initializeDatabase: vi.fn(),
  closeDatabase: vi.fn(),
}));

// Mock diamond economy (required by retention modules)
vi.mock('../../../src/monetization/diamondEconomy.js', () => ({
  awardDiamonds: vi.fn(),
  deductDiamonds: vi.fn(),
  spendDiamonds: vi.fn(),
  getDiamondBalance: vi.fn().mockReturnValue(0),
  initializePlayerDiamonds: vi.fn(),
  DIAMOND_REWARDS: {},
}));

// Mock connectionRegistry (required by diamondEconomy)
vi.mock('../../../src/server/ConnectionRegistry.js', () => ({
  connectionRegistry: {
    getSession: vi.fn(),
    getAllSessions: vi.fn().mockReturnValue([]),
  },
}));

import { sendAchievementUnlocked } from '../../../src/services/retention/integration.js';

// Minimal mock session
function createMockSession() {
  return {
    player: {
      userId: 'test-user',
      deviceToken: 'test-token',
      connection: 'disconnected',
    },
    send: vi.fn(),
  } as any;
}

describe('Notification Triggers', () => {
  beforeEach(() => {
    mockQueueRealtimeNotification.mockClear();
  });

  describe('Achievement Unlock', () => {
    it('should send push notification when achievement is unlocked', () => {
      const session = createMockSession();
      const achievement = {
        id: 'ach-1',
        key: 'first_job',
        name: 'First Job',
        description: 'Got your first job',
        icon: 'briefcase',
        reward: '50 diamonds',
      };

      sendAchievementUnlocked(session, achievement);

      // Should send to client
      expect(session.send).toHaveBeenCalledWith(
        expect.objectContaining({ type: 'achievementUnlocked' })
      );

      // Should queue push notification
      expect(mockQueueRealtimeNotification).toHaveBeenCalledWith(
        session.player,
        expect.objectContaining({
          title: 'Achievement Unlocked!',
          body: 'First Job — 50 diamonds',
          type: 'milestone',
        })
      );
    });

    it('should handle achievement without reward', () => {
      const session = createMockSession();
      const achievement = {
        id: 'ach-2',
        key: 'first_friend',
        name: 'First Friend',
        description: 'Made your first friend',
        icon: 'person',
        reward: '',
      };

      sendAchievementUnlocked(session, achievement);

      expect(mockQueueRealtimeNotification).toHaveBeenCalledWith(
        session.player,
        expect.objectContaining({
          title: 'Achievement Unlocked!',
          body: 'First Friend',
          type: 'milestone',
        })
      );
    });

    it('should pass achievement id in push notification', () => {
      const session = createMockSession();
      const achievement = {
        id: 'ach-3',
        key: 'millionaire',
        name: 'Millionaire',
        description: 'Earned a million dollars',
        icon: 'dollar',
        reward: '100 diamonds',
      };

      sendAchievementUnlocked(session, achievement);

      expect(mockQueueRealtimeNotification).toHaveBeenCalledWith(
        session.player,
        expect.objectContaining({
          id: 'ach-3',
        })
      );
    });

    it('should send achievement details to client via session.send', () => {
      const session = createMockSession();
      const achievement = {
        id: 'ach-4',
        key: 'graduate_hs',
        name: 'High School Graduate',
        description: 'Graduated from high school',
        icon: 'graduation',
        reward: '25 diamonds',
      };

      sendAchievementUnlocked(session, achievement);

      expect(session.send).toHaveBeenCalledWith({
        type: 'achievementUnlocked',
        achievement: {
          id: 'ach-4',
          key: 'graduate_hs',
          name: 'High School Graduate',
          description: 'Graduated from high school',
          icon: 'graduation',
          reward: '25 diamonds',
        },
      });
    });
  });
});
