import { describe, it, expect, vi, beforeEach } from 'vitest';
import { UserbotManager } from './manager.js';

// Mock the UserbotClient to avoid real Telegram connections
vi.mock('./client.js', () => ({
  UserbotClient: vi.fn().mockImplementation((cfg: any) => ({
    characterId: cfg.characterId,
    _cfg: cfg,
    onMessage: vi.fn(),
    start: vi.fn().mockResolvedValue('mock-session-string'),
    reconnect: vi.fn().mockResolvedValue(undefined),
    disconnect: vi.fn().mockResolvedValue(undefined),
    isConnected: vi.fn().mockReturnValue(true),
  })),
}));

// Mock file-ops to avoid real file I/O
vi.mock('../data-store/file-ops.js', () => ({
  readJSON: vi.fn().mockResolvedValue([]),
  atomicWriteJSON: vi.fn().mockResolvedValue(undefined),
  ensureDir: vi.fn().mockResolvedValue(undefined),
}));

function createMockDataStore(character: any = null) {
  return {
    getCharacter: vi.fn().mockResolvedValue(character),
    saveCharacter: vi.fn(),
    listCharacters: vi.fn(),
    init: vi.fn(),
  } as any;
}

const sampleCharacterWithCreds = {
  id: 'char-1',
  identity: { name: 'TestChar' },
  apiCredentials: {
    telegramApiId: 12345,
    telegramApiHash: 'abc123hash',
  },
};

const sampleCharacterNoCreds = {
  id: 'char-2',
  identity: { name: 'NoCreds' },
};

describe('UserbotManager - character-based credentials', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe('login()', () => {
    it('should use character apiCredentials when available', async () => {
      const mockStore = createMockDataStore(sampleCharacterWithCreds);
      const manager = new UserbotManager(mockStore);

      const { UserbotClient } = await import('./client.js');

      await manager.login('char-1', '+905551234567', async () => '12345');

      expect(mockStore.getCharacter).toHaveBeenCalledWith('char-1');
      expect(UserbotClient).toHaveBeenCalledWith(
        expect.objectContaining({
          characterId: 'char-1',
          phoneNumber: '+905551234567',
          telegramApiId: 12345,
          telegramApiHash: 'abc123hash',
        }),
      );
    });

    it('should throw meaningful error when character not found', async () => {
      const mockStore = createMockDataStore(null);
      const manager = new UserbotManager(mockStore);

      await expect(
        manager.login('nonexistent', '+905551234567', async () => '12345'),
      ).rejects.toThrow('Character "nonexistent" not found');
    });

    it('should throw meaningful error when apiCredentials are missing', async () => {
      const mockStore = createMockDataStore(sampleCharacterNoCreds);
      const manager = new UserbotManager(mockStore);

      await expect(
        manager.login('char-2', '+905551234567', async () => '12345'),
      ).rejects.toThrow('API credentials are not configured for character "char-2"');
    });

    it('should throw meaningful error when telegramApiId is 0', async () => {
      const charWithZeroId = {
        ...sampleCharacterWithCreds,
        apiCredentials: { telegramApiId: 0, telegramApiHash: 'hash' },
      };
      const mockStore = createMockDataStore(charWithZeroId);
      const manager = new UserbotManager(mockStore);

      await expect(
        manager.login('char-1', '+905551234567', async () => '12345'),
      ).rejects.toThrow('API credentials are not configured');
    });

    it('should throw meaningful error when telegramApiHash is empty', async () => {
      const charWithEmptyHash = {
        ...sampleCharacterWithCreds,
        apiCredentials: { telegramApiId: 12345, telegramApiHash: '' },
      };
      const mockStore = createMockDataStore(charWithEmptyHash);
      const manager = new UserbotManager(mockStore);

      await expect(
        manager.login('char-1', '+905551234567', async () => '12345'),
      ).rejects.toThrow('API credentials are not configured');
    });

    it('should throw error when DataStore is not provided', async () => {
      const manager = new UserbotManager();

      await expect(
        manager.login('char-1', '+905551234567', async () => '12345'),
      ).rejects.toThrow('DataStore is not available');
    });
  });
});
