import { describe, it, expect, vi, beforeEach } from 'vitest';
import { render, screen, fireEvent, act } from '@testing-library/react';
import { ThemeProvider, useTheme } from '../../src/components/ThemeProvider';
import { Providers } from '../../src/components/Providers';

// Mock next-auth SessionProvider
vi.mock('next-auth/react', () => ({
  SessionProvider: ({ children }: { children: React.ReactNode }) => <>{children}</>,
}));

function ThemeConsumer() {
  const { theme, accent, setTheme, setAccent, toggleTheme } = useTheme();
  return (
    <div>
      <span data-testid="theme">{theme}</span>
      <span data-testid="accent">{accent}</span>
      <button onClick={() => setTheme('dark')}>Set dark</button>
      <button onClick={() => setAccent('cobalt')}>Set cobalt</button>
      <button onClick={toggleTheme}>Toggle</button>
    </div>
  );
}

describe('ThemeProvider', () => {
  beforeEach(() => {
    localStorage.clear();
    document.documentElement.removeAttribute('data-theme');
    document.documentElement.style.cssText = '';
  });

  it('provides default light/sage theme', () => {
    render(
      <ThemeProvider>
        <ThemeConsumer />
      </ThemeProvider>,
    );

    expect(screen.getByTestId('theme').textContent).toBe('light');
    expect(screen.getByTestId('accent').textContent).toBe('sage');
  });

  it('hydrates from localStorage', () => {
    localStorage.setItem('mt-theme', 'dark');
    localStorage.setItem('mt-accent', 'terracotta');

    render(
      <ThemeProvider>
        <ThemeConsumer />
      </ThemeProvider>,
    );

    expect(screen.getByTestId('theme').textContent).toBe('dark');
    expect(screen.getByTestId('accent').textContent).toBe('terracotta');
  });

  it('setTheme updates theme and persists', () => {
    render(
      <ThemeProvider>
        <ThemeConsumer />
      </ThemeProvider>,
    );

    act(() => fireEvent.click(screen.getByText('Set dark')));

    expect(screen.getByTestId('theme').textContent).toBe('dark');
    expect(localStorage.getItem('mt-theme')).toBe('dark');
    expect(document.documentElement.getAttribute('data-theme')).toBe('dark');
  });

  it('setAccent updates accent and applies CSS vars', () => {
    render(
      <ThemeProvider>
        <ThemeConsumer />
      </ThemeProvider>,
    );

    act(() => fireEvent.click(screen.getByText('Set cobalt')));

    expect(screen.getByTestId('accent').textContent).toBe('cobalt');
    expect(localStorage.getItem('mt-accent')).toBe('cobalt');
    expect(document.documentElement.style.getPropertyValue('--brand')).toBe('#3b82f6');
  });

  it('toggleTheme flips light to dark', () => {
    render(
      <ThemeProvider>
        <ThemeConsumer />
      </ThemeProvider>,
    );

    act(() => fireEvent.click(screen.getByText('Toggle')));

    expect(screen.getByTestId('theme').textContent).toBe('dark');
  });

  it('toggleTheme flips dark to light', () => {
    localStorage.setItem('mt-theme', 'dark');

    render(
      <ThemeProvider>
        <ThemeConsumer />
      </ThemeProvider>,
    );

    act(() => fireEvent.click(screen.getByText('Toggle')));

    expect(screen.getByTestId('theme').textContent).toBe('light');
  });

  it('useTheme throws outside provider', () => {
    expect(() => render(<ThemeConsumer />)).toThrow('useTheme must be used inside ThemeProvider');
  });
});

describe('Providers', () => {
  it('renders children with session and theme providers', () => {
    render(
      <Providers>
        <span>child content</span>
      </Providers>,
    );

    expect(screen.getByText('child content')).toBeInTheDocument();
  });
});
