import { describe, it, expect, beforeEach } from 'vitest';
import { renderHook, act } from '@testing-library/react';
import { useSettingsStore } from './use-settings';

// Test encoding/decoding utilities directly
describe('Settings encoding/decoding utilities', () => {
  it('should encode API key to base64', () => {
    const testKey = 'sk-test-key-12345';
    const encoded = btoa(testKey);
    expect(encoded).toBe('c2stdGVzdC1rZXktMTIzNDU=');
  });

  it('should decode base64 to API key', () => {
    const encoded = 'c2stdGVzdC1rZXktMTIzNDU=';
    const decoded = atob(encoded);
    expect(decoded).toBe('sk-test-key-12345');
  });

  it('should handle empty strings', () => {
    expect(btoa('')).toBe('');
    expect(atob('')).toBe('');
  });
});

// Mock localStorage
const localStorageMock = (() => {
  let store: Record<string, string> = {};
  return {
    getItem: (key: string) => store[key] || null,
    setItem: (key: string, value: string) => {
      store[key] = value.toString();
    },
    removeItem: (key: string) => {
      delete store[key];
    },
    clear: () => {
      store = {};
    },
  };
})();

Object.defineProperty(global, 'localStorage', {
  value: localStorageMock,
});

describe('useSettingsStore', () => {
  beforeEach(() => {
    localStorageMock.clear();
    // Reset the store before each test
    useSettingsStore.setState({
      apiKey: '',
      baseUrl: 'https://api.openai.com/v1',
      modelName: 'gpt-4-turbo-preview',
      isConfigured: false,
    });
  });

  it('has default initial state', () => {
    const { result } = renderHook(() => useSettingsStore());
    expect(result.current.apiKey).toBe('');
    expect(result.current.baseUrl).toBe('https://api.openai.com/v1');
    expect(result.current.modelName).toBe('gpt-4-turbo-preview');
    expect(result.current.isConfigured).toBe(false);
  });

  it('stores and retrieves API key correctly', () => {
    const testKey = 'sk-test-key-12345';
    const { result } = renderHook(() => useSettingsStore());

    act(() => {
      result.current.actions.setApiKey(testKey);
    });

    // Check that the store has the key
    expect(result.current.apiKey).toBe(testKey);
    expect(result.current.isConfigured).toBe(true);
  });

  it('encodes and decodes API key correctly', () => {
    const testKey = 'sk-test-key-67890';
    const encoded = btoa(testKey);
    const decoded = atob(encoded);

    expect(encoded).toBe('c2stdGVzdC1rZXktNjc4OTA=');
    expect(decoded).toBe(testKey);
  });

  it('sets baseUrl correctly', () => {
    const customUrl = 'https://api.deepseek.com/v1';
    const { result } = renderHook(() => useSettingsStore());

    act(() => {
      result.current.actions.setBaseUrl(customUrl);
    });

    expect(result.current.baseUrl).toBe(customUrl);
  });

  it('sets modelName correctly', () => {
    const customModel = 'deepseek-coder';
    const { result } = renderHook(() => useSettingsStore());

    act(() => {
      result.current.actions.setModelName(customModel);
    });

    expect(result.current.modelName).toBe(customModel);
  });

  it('clears settings correctly', () => {
    const { result } = renderHook(() => useSettingsStore());

    // First set some values
    act(() => {
      result.current.actions.setApiKey('sk-test');
      result.current.actions.setBaseUrl('https://custom.api/v1');
      result.current.actions.setModelName('custom-model');
    });

    expect(result.current.isConfigured).toBe(true);

    // Then clear
    act(() => {
      result.current.actions.clearSettings();
    });

    expect(result.current.apiKey).toBe('');
    expect(result.current.isConfigured).toBe(false);
    // baseUrl and modelName should remain
    expect(result.current.baseUrl).toBe('https://custom.api/v1');
    expect(result.current.modelName).toBe('custom-model');
  });

  it('computes isConfigured based on apiKey presence', () => {
    const { result } = renderHook(() => useSettingsStore());

    expect(result.current.isConfigured).toBe(false);

    act(() => {
      result.current.actions.setApiKey('sk-test-key');
    });

    expect(result.current.isConfigured).toBe(true);

    act(() => {
      result.current.actions.setApiKey('');
    });

    expect(result.current.isConfigured).toBe(false);
  });

  it('handles empty encoded key gracefully', () => {
    // Simulate empty stored key
    localStorageMock.setItem('test01-settings-storage', JSON.stringify({
      state: {
        apiKey: '',
        baseUrl: 'https://api.openai.com/v1',
        modelName: 'gpt-4-turbo-preview',
      },
      version: 0,
    }));

    const { result } = renderHook(() => useSettingsStore());
    expect(result.current.apiKey).toBe('');
    expect(result.current.isConfigured).toBe(false);
  });

  it('handles invalid encoded key gracefully', () => {
    // Simulate invalid base64
    localStorageMock.setItem('test01-settings-storage', JSON.stringify({
      state: {
        apiKey: 'not-valid-base64!',
        baseUrl: 'https://api.openai.com/v1',
        modelName: 'gpt-4-turbo-preview',
      },
      version: 0,
    }));

    const { result } = renderHook(() => useSettingsStore());
    // Should fall back to empty string on decode error
    expect(result.current.apiKey).toBe('');
    expect(result.current.isConfigured).toBe(false);
  });

  describe('atomic selectors', () => {
    it('provides useApiKey hook', () => {
      const { result } = renderHook(() => useSettingsStore((s) => s.apiKey));

      expect(result.current).toBe('');

      act(() => {
        useSettingsStore.getState().actions.setApiKey('sk-test');
      });

      expect(result.current).toBe('sk-test');
    });

    it('provides useBaseUrl hook', () => {
      const { result } = renderHook(() => useSettingsStore((s) => s.baseUrl));

      expect(result.current).toBe('https://api.openai.com/v1');

      act(() => {
        useSettingsStore.getState().actions.setBaseUrl('https://custom.url/v1');
      });

      expect(result.current).toBe('https://custom.url/v1');
    });

    it('provides useModelName hook', () => {
      const { result } = renderHook(() => useSettingsStore((s) => s.modelName));

      expect(result.current).toBe('gpt-4-turbo-preview');

      act(() => {
        useSettingsStore.getState().actions.setModelName('custom-model');
      });

      expect(result.current).toBe('custom-model');
    });

    it('provides useIsConfigured hook', () => {
      const { result } = renderHook(() => useSettingsStore((s) => s.isConfigured));

      expect(result.current).toBe(false);

      act(() => {
        useSettingsStore.getState().actions.setApiKey('sk-test');
      });

      expect(result.current).toBe(true);
    });

    it('provides useSettingsActions hook', () => {
      const { result } = renderHook(() => useSettingsStore((s) => s.actions));

      // Check that legacy actions exist
      expect(result.current.setApiKey).toBeInstanceOf(Function);
      expect(result.current.setBaseUrl).toBeInstanceOf(Function);
      expect(result.current.setModelName).toBeInstanceOf(Function);
      expect(result.current.clearSettings).toBeInstanceOf(Function);

      // Check that new multi-provider actions exist
      expect(result.current.addProvider).toBeInstanceOf(Function);
      expect(result.current.removeProvider).toBeInstanceOf(Function);
      expect(result.current.setActiveProvider).toBeInstanceOf(Function);
      expect(result.current.updateProvider).toBeInstanceOf(Function);
      expect(result.current.completeMigration).toBeInstanceOf(Function);
    });
  });
});
