/**
 * LanguageProvider Tests
 *
 * Tests language context, persistence, and hydration behavior.
 */

import { render, screen, act } from '@testing-library/react';
import { LanguageProvider, useLanguage } from '../LanguageProvider';

// Mock sessionStorage
const mockSessionStorage = (() => {
  let store: Record<string, string> = {};
  return {
    getItem: jest.fn((key: string) => store[key] || null),
    setItem: jest.fn((key: string, value: string) => {
      store[key] = value;
    }),
    clear: () => {
      store = {};
    },
    removeItem: jest.fn((key: string) => {
      delete store[key];
    }),
  };
})();
Object.defineProperty(window, 'sessionStorage', { value: mockSessionStorage });

// Mock document.cookie
let mockCookies: string[] = [];
Object.defineProperty(document, 'cookie', {
  get: () => mockCookies.join('; '),
  set: (value: string) => {
    const [cookiePair] = value.split(';');
    const [name] = cookiePair.split('=');
    // Remove existing cookie with same name
    mockCookies = mockCookies.filter((c) => !c.startsWith(`${name}=`));
    mockCookies.push(cookiePair);
  },
});

// Test component that uses the language context
function TestConsumer() {
  const { language, setLanguage } = useLanguage();
  return (
    <div>
      <span data-testid="language">{language}</span>
      <button onClick={() => setLanguage('es')} data-testid="switch-to-es">
        Switch to Spanish
      </button>
      <button onClick={() => setLanguage('en')} data-testid="switch-to-en">
        Switch to English
      </button>
      <button onClick={() => setLanguage('fr')} data-testid="switch-to-fr">
        Switch to French
      </button>
    </div>
  );
}

describe('LanguageProvider', () => {
  beforeEach(() => {
    mockSessionStorage.clear();
    mockCookies = [];
    jest.clearAllMocks();
  });

  describe('Initial state', () => {
    it('provides defaultLanguage when no stored preference', () => {
      render(
        <LanguageProvider defaultLanguage="en" subdomain="test">
          <TestConsumer />
        </LanguageProvider>
      );

      expect(screen.getByTestId('language')).toHaveTextContent('en');
    });

    it('uses Spanish as defaultLanguage when specified', () => {
      render(
        <LanguageProvider defaultLanguage="es" subdomain="test">
          <TestConsumer />
        </LanguageProvider>
      );

      expect(screen.getByTestId('language')).toHaveTextContent('es');
    });

    it('uses French as defaultLanguage when specified', () => {
      render(
        <LanguageProvider defaultLanguage="fr" subdomain="test">
          <TestConsumer />
        </LanguageProvider>
      );

      expect(screen.getByTestId('language')).toHaveTextContent('fr');
    });
  });

  describe('Language switching', () => {
    it('switches language when setLanguage is called', () => {
      render(
        <LanguageProvider defaultLanguage="en" subdomain="test">
          <TestConsumer />
        </LanguageProvider>
      );

      expect(screen.getByTestId('language')).toHaveTextContent('en');

      act(() => {
        screen.getByTestId('switch-to-es').click();
      });

      expect(screen.getByTestId('language')).toHaveTextContent('es');
    });

    it('can switch to French', () => {
      render(
        <LanguageProvider defaultLanguage="en" subdomain="test">
          <TestConsumer />
        </LanguageProvider>
      );

      act(() => {
        screen.getByTestId('switch-to-fr').click();
      });

      expect(screen.getByTestId('language')).toHaveTextContent('fr');
    });

    it('can switch back and forth between all languages', () => {
      render(
        <LanguageProvider defaultLanguage="en" subdomain="test">
          <TestConsumer />
        </LanguageProvider>
      );

      act(() => {
        screen.getByTestId('switch-to-es').click();
      });
      expect(screen.getByTestId('language')).toHaveTextContent('es');

      act(() => {
        screen.getByTestId('switch-to-fr').click();
      });
      expect(screen.getByTestId('language')).toHaveTextContent('fr');

      act(() => {
        screen.getByTestId('switch-to-en').click();
      });
      expect(screen.getByTestId('language')).toHaveTextContent('en');
    });
  });

  describe('Persistence', () => {
    it('stores language preference in sessionStorage', () => {
      render(
        <LanguageProvider defaultLanguage="en" subdomain="testdealer">
          <TestConsumer />
        </LanguageProvider>
      );

      act(() => {
        screen.getByTestId('switch-to-es').click();
      });

      expect(mockSessionStorage.setItem).toHaveBeenCalledWith('dlp-lang-testdealer', 'es');
    });

    it('stores French preference in sessionStorage', () => {
      render(
        <LanguageProvider defaultLanguage="en" subdomain="testdealer">
          <TestConsumer />
        </LanguageProvider>
      );

      act(() => {
        screen.getByTestId('switch-to-fr').click();
      });

      expect(mockSessionStorage.setItem).toHaveBeenCalledWith('dlp-lang-testdealer', 'fr');
    });

    it('stores language preference in cookie', () => {
      render(
        <LanguageProvider defaultLanguage="en" subdomain="testdealer">
          <TestConsumer />
        </LanguageProvider>
      );

      act(() => {
        screen.getByTestId('switch-to-es').click();
      });

      expect(document.cookie).toContain('dlp-lang-testdealer=es');
    });

    it('uses subdomain-specific storage key', () => {
      render(
        <LanguageProvider defaultLanguage="en" subdomain="dealer1">
          <TestConsumer />
        </LanguageProvider>
      );

      act(() => {
        screen.getByTestId('switch-to-es').click();
      });

      expect(mockSessionStorage.setItem).toHaveBeenCalledWith('dlp-lang-dealer1', 'es');
    });
  });

  describe('Hydration from storage', () => {
    it('reads language from cookie on mount', () => {
      mockCookies = ['dlp-lang-testdealer=es'];

      render(
        <LanguageProvider defaultLanguage="en" subdomain="testdealer">
          <TestConsumer />
        </LanguageProvider>
      );

      // After hydration, should show Spanish
      expect(screen.getByTestId('language')).toHaveTextContent('es');
    });

    it('reads French from cookie on mount', () => {
      mockCookies = ['dlp-lang-testdealer=fr'];

      render(
        <LanguageProvider defaultLanguage="en" subdomain="testdealer">
          <TestConsumer />
        </LanguageProvider>
      );

      expect(screen.getByTestId('language')).toHaveTextContent('fr');
    });

    it('falls back to sessionStorage if no cookie', () => {
      mockSessionStorage.getItem.mockImplementation((key: string) => {
        if (key === 'dlp-lang-testdealer') return 'es';
        return null;
      });

      render(
        <LanguageProvider defaultLanguage="en" subdomain="testdealer">
          <TestConsumer />
        </LanguageProvider>
      );

      expect(screen.getByTestId('language')).toHaveTextContent('es');
    });

    it('uses defaultLanguage if no stored preference', () => {
      render(
        <LanguageProvider defaultLanguage="en" subdomain="newdealer">
          <TestConsumer />
        </LanguageProvider>
      );

      expect(screen.getByTestId('language')).toHaveTextContent('en');
    });
  });

  describe('useLanguage hook', () => {
    it('throws error when used outside provider', () => {
      // Suppress console.error for this test
      const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {});

      expect(() => {
        render(<TestConsumer />);
      }).toThrow('useLanguage must be used within a LanguageProvider');

      consoleSpy.mockRestore();
    });
  });
});
