import { describe, it, expect, beforeEach, vi } from 'vitest';
import { ChatService } from './chat-service';
import { ProviderManagementService } from './provider-management-service';
import { db } from '@/lib/db/db';
import { useSettingsStore } from '@/store/use-settings';
import { v4 as uuidv4 } from 'uuid';

// Mock UUID
vi.mock('uuid', () => ({
  v4: () => 'mock-uuid-1234',
}));

// Mock database
vi.mock('@/lib/db/db', () => ({
  db: {
    sessions: {
      add: vi.fn(),
      update: vi.fn(),
    },
    chatLogs: {
      add: vi.fn(),
      where: vi.fn(() => ({
        equals: vi.fn(() => ({
          sortBy: vi.fn(() => Promise.resolve([])),
        })),
      })),
    },
  },
}));

// Mock session store
vi.mock('@/store/use-session', () => ({
  useSessionStore: {
    getState: () => ({
      actions: {
        setTeacherStatus: vi.fn(),
      },
    }),
  },
}));

// Mock LLM service
vi.mock('./llm-service', () => ({
  LLMService: {
    generateResponse: vi.fn(),
  },
}));

describe('ChatService with Settings Integration', () => {
  beforeEach(() => {
    vi.clearAllMocks();

    // Reset settings store - including migration state
    useSettingsStore.setState({
      apiKey: '',
      baseUrl: 'https://api.openai.com/v1',
      modelName: 'gpt-4o',
      isConfigured: false,
      savedProviders: [],
      activeProviderId: null,
      providerMigrationState: {
        hasMigrated: false,
      },
    });
  });

  it('throws error when provider not configured', async () => {
    await expect(ChatService.sendMessage('Hello', 'session-123')).rejects.toThrow(
      'AI Provider not configured'
    );
  });

  it('retrieves credentials from active provider when sending message', async () => {
    const { LLMService } = await import('./llm-service');

    // Configure a provider using ProviderManagementService
    ProviderManagementService.addProviderProfile({
      name: 'Test Provider',
      baseUrl: 'https://api.deepseek.com/v1',
      apiKey: 'sk-test-key-45678',
      modelName: 'deepseek-chat',
    });

    vi.mocked(LLMService.generateResponse).mockResolvedValue('Test response');

    await ChatService.sendMessage('Hello, AI!', 'session-123');

    expect(LLMService.generateResponse).toHaveBeenCalledWith({
      apiKey: 'sk-test-key-45678',
      baseUrl: 'https://api.deepseek.com/v1',
      model: 'deepseek-chat',
      messages: expect.any(Array),
    });
  });

  it('uses active provider settings for LLM calls', async () => {
    const { LLMService } = await import('./llm-service');

    // Add a custom provider
    ProviderManagementService.addProviderProfile({
      name: 'Custom Provider',
      baseUrl: 'https://custom.api.com/v1',
      apiKey: 'sk-custom-key',
      modelName: 'custom-model-name',
    });

    vi.mocked(LLMService.generateResponse).mockResolvedValue('Custom response');

    await ChatService.sendMessage('Test message', 'session-456');

    expect(LLMService.generateResponse).toHaveBeenCalledWith(
      expect.objectContaining({
        apiKey: 'sk-custom-key',
        baseUrl: 'https://custom.api.com/v1',
        model: 'custom-model-name',
      })
    );
  });

  it('provider switching takes effect immediately for next message', async () => {
    const { LLMService } = await import('./llm-service');

    // Add OpenAI provider
    const openaiId = ProviderManagementService.addProviderProfile({
      name: 'OpenAI',
      baseUrl: 'https://api.openai.com/v1',
      apiKey: 'sk-openai-key',
      modelName: 'gpt-4o',
    });

    // Add DeepSeek provider
    const deepseekId = ProviderManagementService.addProviderProfile({
      name: 'DeepSeek',
      baseUrl: 'https://api.deepseek.com/v1',
      apiKey: 'sk-deepseek-key',
      modelName: 'deepseek-chat',
    });

    // OpenAI is active (first provider)
    expect(ProviderManagementService.getActiveProvider()?.name).toBe('OpenAI');

    vi.mocked(LLMService.generateResponse).mockResolvedValue('OpenAI response');

    await ChatService.sendMessage('First message', 'session-1');

    expect(LLMService.generateResponse).toHaveBeenCalledWith(
      expect.objectContaining({
        apiKey: 'sk-openai-key',
        baseUrl: 'https://api.openai.com/v1',
        model: 'gpt-4o',
      })
    );

    // Switch to DeepSeek
    ProviderManagementService.setActiveProvider(deepseekId);

    // DeepSeek is now active
    expect(ProviderManagementService.getActiveProvider()?.name).toBe('DeepSeek');

    vi.mocked(LLMService.generateResponse).mockResolvedValue('DeepSeek response');

    await ChatService.sendMessage('Second message', 'session-1');

    expect(LLMService.generateResponse).toHaveBeenCalledWith(
      expect.objectContaining({
        apiKey: 'sk-deepseek-key',
        baseUrl: 'https://api.deepseek.com/v1',
        model: 'deepseek-chat',
      })
    );
  });

  it('uses default settings when no active provider', () => {
    const settings = ProviderManagementService.getActiveProviderSettings();

    expect(settings.apiKey).toBe('');
    expect(settings.baseUrl).toBe('https://api.openai.com/v1');
    expect(settings.modelName).toBe('gpt-4o');
  });
});
