import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { signIn } from 'next-auth/react';
import SignInContent from '../SignInContent';

// Mock next-auth
jest.mock('next-auth/react', () => ({
  signIn: jest.fn(),
}));

const mockSignIn = signIn as jest.MockedFunction<typeof signIn>;

// Mock next/navigation
const mockSearchParams = new Map();
jest.mock('next/navigation', () => ({
  useSearchParams: () => ({
    get: (key: string) => mockSearchParams.get(key) || null,
  }),
}));

// Mock next/image
jest.mock('next/image', () => ({
  __esModule: true,
  default: ({ src, alt, ...props }: { src: string; alt: string }) => (
    // eslint-disable-next-line @next/next/no-img-element
    <img src={src} alt={alt} {...props} />
  ),
}));

// Mock the EmailAuthForm
jest.mock('../EmailAuthForm', () => ({
  __esModule: true,
  default: ({ defaultMode, callbackUrl }: { defaultMode: string; callbackUrl: string }) => (
    <div
      data-testid="email-auth-form"
      data-default-mode={defaultMode}
      data-callback-url={callbackUrl}
    >
      <p>Email Auth Form Mock (mode: {defaultMode})</p>
    </div>
  ),
}));

// Mock the OrDivider
jest.mock('../OrDivider', () => ({
  __esModule: true,
  default: () => <div data-testid="or-divider">OR</div>,
}));

describe('SignInContent', () => {
  const defaultProps = {
    callbackUrl: '/dashboard',
    subtitle: 'Sign in to continue',
  };

  beforeEach(() => {
    jest.clearAllMocks();
    mockSearchParams.clear();
  });

  describe('Rendering', () => {
    it('renders OAuth buttons', () => {
      render(<SignInContent {...defaultProps} />);

      expect(screen.getByRole('button', { name: /sign in with google/i })).toBeInTheDocument();
      expect(screen.getByRole('button', { name: /sign in with apple/i })).toBeInTheDocument();
    });

    it('renders OR divider', () => {
      render(<SignInContent {...defaultProps} />);

      expect(screen.getByTestId('or-divider')).toBeInTheDocument();
    });

    it('renders EmailAuthForm component', () => {
      render(<SignInContent {...defaultProps} />);

      expect(screen.getByTestId('email-auth-form')).toBeInTheDocument();
    });

    it('renders default heading for dashboard access', () => {
      render(<SignInContent {...defaultProps} />);

      const heading = screen.getByRole('heading', { level: 1 });
      expect(heading).toHaveTextContent('Access Your');
      expect(heading).toHaveTextContent('Dashboard');
    });

    it('renders subscription heading when isSubscriptionFlow is true', () => {
      render(
        <SignInContent {...defaultProps} isSubscriptionFlow={true} displayPlanName="Starter" />
      );

      const heading = screen.getByRole('heading', { level: 1 });
      expect(heading).toHaveTextContent('Subscribe');
      expect(heading).toHaveTextContent('Starter Plan');
    });

    it('renders subtitle', () => {
      render(<SignInContent {...defaultProps} />);

      expect(screen.getByText('Sign in to continue')).toBeInTheDocument();
    });

    it('renders disclaimer text', () => {
      render(<SignInContent {...defaultProps} />);

      expect(screen.getByText(/terms of service/i)).toBeInTheDocument();
    });
  });

  describe('EmailAuthForm Default Mode', () => {
    it('passes signin mode to EmailAuthForm for normal flow', () => {
      render(<SignInContent {...defaultProps} />);

      const emailForm = screen.getByTestId('email-auth-form');
      expect(emailForm).toHaveAttribute('data-default-mode', 'signin');
    });

    it('passes signup mode to EmailAuthForm for subscription flow', () => {
      render(
        <SignInContent {...defaultProps} isSubscriptionFlow={true} displayPlanName="Growth" />
      );

      const emailForm = screen.getByTestId('email-auth-form');
      expect(emailForm).toHaveAttribute('data-default-mode', 'signup');
    });

    it('passes callbackUrl to EmailAuthForm', () => {
      render(<SignInContent {...defaultProps} callbackUrl="/custom-url" />);

      const emailForm = screen.getByTestId('email-auth-form');
      expect(emailForm).toHaveAttribute('data-callback-url', '/custom-url');
    });

    it('defaults callbackUrl to /dashboard when not provided', () => {
      render(<SignInContent subtitle="Test" />);

      const emailForm = screen.getByTestId('email-auth-form');
      expect(emailForm).toHaveAttribute('data-callback-url', '/dashboard');
    });
  });

  describe('OAuth Sign In', () => {
    it('calls signIn with google provider when Google button clicked', async () => {
      const user = userEvent.setup();
      render(<SignInContent {...defaultProps} />);

      await user.click(screen.getByRole('button', { name: /sign in with google/i }));

      expect(mockSignIn).toHaveBeenCalledWith('google', {
        callbackUrl: '/dashboard',
      });
    });

    it('calls signIn with apple provider when Apple button clicked', async () => {
      const user = userEvent.setup();
      render(<SignInContent {...defaultProps} />);

      await user.click(screen.getByRole('button', { name: /sign in with apple/i }));

      expect(mockSignIn).toHaveBeenCalledWith('apple', {
        callbackUrl: '/dashboard',
      });
    });

    it('uses custom callbackUrl when provided', async () => {
      const user = userEvent.setup();
      const customUrl = '/checkout?plan=starter';
      render(<SignInContent {...defaultProps} callbackUrl={customUrl} />);

      await user.click(screen.getByRole('button', { name: /sign in with google/i }));

      expect(mockSignIn).toHaveBeenCalledWith('google', {
        callbackUrl: customUrl,
      });
    });

    it('defaults to /dashboard when no callbackUrl provided', async () => {
      const user = userEvent.setup();
      render(<SignInContent subtitle="Test" />);

      await user.click(screen.getByRole('button', { name: /sign in with google/i }));

      expect(mockSignIn).toHaveBeenCalledWith('google', {
        callbackUrl: '/dashboard',
      });
    });
  });

  describe('Error Display', () => {
    it('shows OAuthAccountNotLinked error message', () => {
      mockSearchParams.set('error', 'OAuthAccountNotLinked');
      render(<SignInContent {...defaultProps} />);

      expect(
        screen.getByText(/already associated with another sign-in method/i)
      ).toBeInTheDocument();
    });

    it('shows CredentialsSignin error message', () => {
      mockSearchParams.set('error', 'CredentialsSignin');
      render(<SignInContent {...defaultProps} />);

      expect(screen.getByText(/invalid email or password/i)).toBeInTheDocument();
    });

    it('shows generic error message for unknown errors', () => {
      mockSearchParams.set('error', 'SomeUnknownError');
      render(<SignInContent {...defaultProps} />);

      expect(screen.getByText(/an error occurred during sign in/i)).toBeInTheDocument();
    });

    it('does not show error when no error in params', () => {
      render(<SignInContent {...defaultProps} />);

      expect(screen.queryByText(/already associated/i)).not.toBeInTheDocument();
      expect(screen.queryByText(/invalid email or password/i)).not.toBeInTheDocument();
      expect(screen.queryByText(/an error occurred/i)).not.toBeInTheDocument();
    });
  });

  describe('Layout Order', () => {
    it('renders elements in correct order: OAuth buttons, divider, form, disclaimer', () => {
      render(<SignInContent {...defaultProps} />);

      const container = document.querySelector('.space-y-3');
      const children = container?.children;

      expect(children).toBeDefined();
      if (children) {
        // Find the indices of key elements
        const googleButton = screen.getByRole('button', { name: /sign in with google/i });
        const appleButton = screen.getByRole('button', { name: /sign in with apple/i });
        const orDivider = screen.getByTestId('or-divider');
        const emailForm = screen.getByTestId('email-auth-form');
        const disclaimer = screen.getByText(/terms of service/i);

        // Verify all elements are present
        expect(googleButton).toBeInTheDocument();
        expect(appleButton).toBeInTheDocument();
        expect(orDivider).toBeInTheDocument();
        expect(emailForm).toBeInTheDocument();
        expect(disclaimer).toBeInTheDocument();
      }
    });
  });

  describe('Accessibility', () => {
    it('has proper aria-label on Google button', () => {
      render(<SignInContent {...defaultProps} />);

      const googleButton = screen.getByRole('button', { name: /sign in with google/i });
      expect(googleButton).toHaveAttribute('aria-label', 'Sign in with Google');
    });

    it('has proper aria-label on Apple button', () => {
      render(<SignInContent {...defaultProps} />);

      const appleButton = screen.getByRole('button', { name: /sign in with apple/i });
      expect(appleButton).toHaveAttribute('aria-label', 'Sign in with Apple');
    });

    it('has type=button on OAuth buttons to prevent form submission', () => {
      render(<SignInContent {...defaultProps} />);

      expect(screen.getByRole('button', { name: /sign in with google/i })).toHaveAttribute(
        'type',
        'button'
      );
      expect(screen.getByRole('button', { name: /sign in with apple/i })).toHaveAttribute(
        'type',
        'button'
      );
    });
  });
});
