/**
 * Tests for Provider Management Service
 * Story 4.4: Provider Switching
 */

import { describe, it, expect, beforeEach } from 'vitest';
import { renderHook, act } from '@testing-library/react';
import { ProviderManagementService } from './provider-management-service';
import { useSettingsStore } from '@/store/use-settings';
import type { ProviderProfile } from '@/types/settings';

describe('ProviderManagementService', () => {
  beforeEach(() => {
    // Reset store state before each test
    useSettingsStore.getState().actions.clearSettings();
    useSettingsStore.setState({
      providerMigrationState: {
        hasMigrated: false,
      },
      savedProviders: [],
      activeProviderId: null,
    });
  });

  describe('getActiveProvider', () => {
    it('should return null when no providers exist', () => {
      const active = ProviderManagementService.getActiveProvider();
      expect(active).toBeNull();
    });

    it('should return null when no provider is active', () => {
      const { actions } = useSettingsStore.getState();

      act(() => {
        actions.addProvider({
          name: 'Test Provider',
          baseUrl: 'https://api.test.com/v1',
          apiKey: 'sk-test',
          modelName: 'test-model',
        });
      });

      // Manually clear the active provider
      act(() => {
        useSettingsStore.setState({ activeProviderId: null });
      });

      const active = ProviderManagementService.getActiveProvider();
      expect(active).toBeNull();
    });

    it('should return the active provider profile', () => {
      const { actions } = useSettingsStore.getState();

      const profile: Omit<ProviderProfile, 'id' | 'createdAt' | 'updatedAt'> = {
        name: 'Active Provider',
        baseUrl: 'https://api.active.com/v1',
        apiKey: 'sk-active',
        modelName: 'active-model',
      };

      act(() => {
        actions.addProvider(profile);
      });

      const active = ProviderManagementService.getActiveProvider();
      expect(active).toBeTruthy();
      expect(active?.name).toBe('Active Provider');
      expect(active?.baseUrl).toBe('https://api.active.com/v1');
      expect(active?.apiKey).toBe('sk-active');
      expect(active?.modelName).toBe('active-model');
    });

    it('should return null when activeProviderId points to non-existent provider', () => {
      const { actions } = useSettingsStore.getState();

      act(() => {
        actions.setActiveProvider('non-existent-id');
      });

      const active = ProviderManagementService.getActiveProvider();
      expect(active).toBeNull();
    });
  });

  describe('getAllProviders', () => {
    it('should return empty array when no providers exist', () => {
      const providers = ProviderManagementService.getAllProviders();
      expect(providers).toEqual([]);
    });

    it('should return all saved providers', () => {
      const { actions } = useSettingsStore.getState();

      act(() => {
        actions.addProvider({
          name: 'Provider 1',
          baseUrl: 'https://api.p1.com/v1',
          apiKey: 'sk-p1',
          modelName: 'model1',
        });
        actions.addProvider({
          name: 'Provider 2',
          baseUrl: 'https://api.p2.com/v1',
          apiKey: 'sk-p2',
          modelName: 'model2',
        });
      });

      const providers = ProviderManagementService.getAllProviders();
      expect(providers).toHaveLength(2);
      expect(providers[0].name).toBe('Provider 1');
      expect(providers[1].name).toBe('Provider 2');
    });
  });

  describe('addProviderProfile', () => {
    it('should add a new provider and return its ID', () => {
      const profile: Omit<ProviderProfile, 'id' | 'createdAt' | 'updatedAt'> = {
        name: 'New Provider',
        baseUrl: 'https://api.new.com/v1',
        apiKey: 'sk-new',
        modelName: 'new-model',
      };

      const id = ProviderManagementService.addProviderProfile(profile);

      expect(id).toBeTruthy();
      expect(id).toMatch(/^provider-\d+-[a-z0-9]+$/);

      const providers = ProviderManagementService.getAllProviders();
      expect(providers).toHaveLength(1);
      expect(providers[0].id).toBe(id);
      expect(providers[0].name).toBe('New Provider');
    });

    it('should auto-select first provider as active', () => {
      const profile: Omit<ProviderProfile, 'id' | 'createdAt' | 'updatedAt'> = {
        name: 'First Provider',
        baseUrl: 'https://api.first.com/v1',
        apiKey: 'sk-first',
        modelName: 'first-model',
      };

      ProviderManagementService.addProviderProfile(profile);

      const active = ProviderManagementService.getActiveProvider();
      expect(active).toBeTruthy();
      expect(active?.name).toBe('First Provider');
    });

    it('should NOT auto-select subsequent providers', () => {
      const { actions } = useSettingsStore.getState();

      const firstId = ProviderManagementService.addProviderProfile({
        name: 'First Provider',
        baseUrl: 'https://api.first.com/v1',
        apiKey: 'sk-first',
        modelName: 'first-model',
      });

      const secondId = ProviderManagementService.addProviderProfile({
        name: 'Second Provider',
        baseUrl: 'https://api.second.com/v1',
        apiKey: 'sk-second',
        modelName: 'second-model',
      });

      const activeId = useSettingsStore.getState().activeProviderId;
      expect(activeId).toBe(firstId);
      expect(activeId).not.toBe(secondId);
    });
  });

  describe('removeProviderProfile', () => {
    it('should remove a provider by ID', () => {
      const id = ProviderManagementService.addProviderProfile({
        name: 'To Remove',
        baseUrl: 'https://api.remove.com/v1',
        apiKey: 'sk-remove',
        modelName: 'remove-model',
      });

      expect(ProviderManagementService.getAllProviders()).toHaveLength(1);

      ProviderManagementService.removeProviderProfile(id);

      expect(ProviderManagementService.getAllProviders()).toHaveLength(0);
    });

    it('should auto-select another provider when removing active provider', () => {
      const id1 = ProviderManagementService.addProviderProfile({
        name: 'Provider 1',
        baseUrl: 'https://api.p1.com/v1',
        apiKey: 'sk-p1',
        modelName: 'model1',
      });

      const id2 = ProviderManagementService.addProviderProfile({
        name: 'Provider 2',
        baseUrl: 'https://api.p2.com/v1',
        apiKey: 'sk-p2',
        modelName: 'model2',
      });

      // Provider 1 is active
      expect(ProviderManagementService.getActiveProvider()?.name).toBe('Provider 1');

      ProviderManagementService.removeProviderProfile(id1);

      // Provider 2 should now be active
      expect(ProviderManagementService.getActiveProvider()?.name).toBe('Provider 2');
    });

    it('should set activeProviderId to null when removing last provider', () => {
      const id = ProviderManagementService.addProviderProfile({
        name: 'Only Provider',
        baseUrl: 'https://api.only.com/v1',
        apiKey: 'sk-only',
        modelName: 'only-model',
      });

      expect(ProviderManagementService.getActiveProvider()).toBeTruthy();

      ProviderManagementService.removeProviderProfile(id);

      expect(ProviderManagementService.getActiveProvider()).toBeNull();
      expect(useSettingsStore.getState().activeProviderId).toBeNull();
    });

    it('should not change active provider when removing non-active provider', () => {
      const id1 = ProviderManagementService.addProviderProfile({
        name: 'Active Provider',
        baseUrl: 'https://api.active.com/v1',
        apiKey: 'sk-active',
        modelName: 'active-model',
      });

      ProviderManagementService.addProviderProfile({
        name: 'Other Provider',
        baseUrl: 'https://api.other.com/v1',
        apiKey: 'sk-other',
        modelName: 'other-model',
      });

      const activeBefore = ProviderManagementService.getActiveProvider();

      ProviderManagementService.removeProviderProfile(id1 === activeBefore?.id ? id1 : id1);

      const activeAfter = ProviderManagementService.getActiveProvider();
      expect(activeAfter?.name).toBe('Other Provider');
    });
  });

  describe('setActiveProvider', () => {
    it('should set the active provider by ID', () => {
      const id1 = ProviderManagementService.addProviderProfile({
        name: 'Provider 1',
        baseUrl: 'https://api.p1.com/v1',
        apiKey: 'sk-p1',
        modelName: 'model1',
      });

      const id2 = ProviderManagementService.addProviderProfile({
        name: 'Provider 2',
        baseUrl: 'https://api.p2.com/v1',
        apiKey: 'sk-p2',
        modelName: 'model2',
      });

      ProviderManagementService.setActiveProvider(id2);

      const active = ProviderManagementService.getActiveProvider();
      expect(active?.id).toBe(id2);
      expect(active?.name).toBe('Provider 2');
    });
  });

  describe('updateProviderProfile', () => {
    it('should update provider fields', () => {
      const id = ProviderManagementService.addProviderProfile({
        name: 'Original Name',
        baseUrl: 'https://api.original.com/v1',
        apiKey: 'sk-original',
        modelName: 'original-model',
      });

      ProviderManagementService.updateProviderProfile(id, {
        name: 'Updated Name',
        modelName: 'updated-model',
      });

      const providers = ProviderManagementService.getAllProviders();
      const updated = providers.find(p => p.id === id);

      expect(updated?.name).toBe('Updated Name');
      expect(updated?.modelName).toBe('updated-model');
      expect(updated?.baseUrl).toBe('https://api.original.com/v1'); // Unchanged
      expect(updated?.apiKey).toBe('sk-original'); // Unchanged
      expect(updated?.createdAt).toBeTruthy(); // Original createdAt preserved
      expect(updated?.updatedAt).toBeTruthy(); // updatedAt updated
    });
  });

  describe('getActiveProviderSettings', () => {
    it('should return ProviderSettings for active provider', () => {
      ProviderManagementService.addProviderProfile({
        name: 'Test Provider',
        baseUrl: 'https://api.test.com/v1',
        apiKey: 'sk-test-key',
        modelName: 'test-model',
      });

      const settings = ProviderManagementService.getActiveProviderSettings();

      expect(settings.apiKey).toBe('sk-test-key');
      expect(settings.baseUrl).toBe('https://api.test.com/v1');
      expect(settings.modelName).toBe('test-model');
    });

    it('should return empty defaults 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');
    });

    it('should return ProviderSettings format compatible with legacy interface', () => {
      ProviderManagementService.addProviderProfile({
        name: 'Test Provider',
        baseUrl: 'https://api.test.com/v1',
        apiKey: 'sk-test',
        modelName: 'test-model',
      });

      const settings = ProviderManagementService.getActiveProviderSettings();

      // Should have the expected properties
      expect(settings).toHaveProperty('apiKey');
      expect(settings).toHaveProperty('baseUrl');
      expect(settings).toHaveProperty('modelName');
    });
  });

  describe('hasAnyProvider', () => {
    it('should return false when no providers exist', () => {
      expect(ProviderManagementService.hasAnyProvider()).toBe(false);
    });

    it('should return true when at least one provider exists', () => {
      expect(ProviderManagementService.hasAnyProvider()).toBe(false);

      ProviderManagementService.addProviderProfile({
        name: 'Test Provider',
        baseUrl: 'https://api.test.com/v1',
        apiKey: 'sk-test',
        modelName: 'test-model',
      });

      expect(ProviderManagementService.hasAnyProvider()).toBe(true);
    });
  });
});
