/**
 * (branches: loading vs guest vs authed redirect; contract mocks).
 */
import React from 'react'
import { render, screen, waitFor } from '@testing-library/react'

const mockPush = jest.fn()

jest.mock('@/providers/auth-provider', () => ({
  useAuth: jest.fn(),
}))

jest.mock('@/i18n/navigation', () => ({
  useRouter: jest.fn(() => ({
    push: mockPush,
    replace: jest.fn(),
  })),
}))

jest.mock('@/providers/auth-session-provider', () => ({
  AuthSessionProvider: ({
    children,
    authSession,
  }: {
    children: React.ReactNode
    authSession: unknown
  }) => (
    <div data-testid="session-wrap" data-has-session={authSession ? '1' : '0'}>
      {children}
    </div>
  ),
}))

jest.mock('@/share/layout/auth', () => ({
  __esModule: true,
  default: ({ children }: { children: React.ReactNode }) => (
    <div data-testid="auth-view-layout">{children}</div>
  ),
}))

jest.mock('@/share/components/full-page/loading', () => ({
  __esModule: true,
  default: () => <div data-testid="loading-page">Loading</div>,
}))

import * as Auth from '@/providers/auth-provider'
import AuthLayout from '../layout'

const useAuthMock = Auth.useAuth as unknown as jest.Mock

describe('[locale]/(auth)/layout.tsx — AuthLayout', () => {
  beforeEach(() => {
    jest.clearAllMocks()
    useAuthMock.mockReturnValue({
      isLoading: false,
      authInfo: null,
    })
  })

  describe('loading branch', () => {
    it('shows LoadingPage only; no redirect, no exposed children yet', () => {
      useAuthMock.mockReturnValue({
        isLoading: true,
        authInfo: null,
      })

      render(
        <AuthLayout>
          <div>Auth child</div>
        </AuthLayout>
      )

      expect(screen.getByTestId('loading-page')).toBeInTheDocument()
      expect(screen.queryByText('Auth child')).not.toBeInTheDocument()
      expect(mockPush).not.toHaveBeenCalled()
    })
  })

  describe('guest branch (happy path for auth routes)', () => {
    it('renders AuthViewLayout + session shell with authSession null; no redirect', () => {
      render(
        <AuthLayout>
          <div>Auth child</div>
        </AuthLayout>
      )

      expect(screen.queryByTestId('loading-page')).not.toBeInTheDocument()
      expect(screen.getByText('Auth child')).toBeInTheDocument()
      expect(screen.getByTestId('auth-view-layout')).toBeInTheDocument()
      expect(mockPush).not.toHaveBeenCalled()
      expect(screen.getByTestId('session-wrap')).toHaveAttribute(
        'data-has-session',
        '0'
      )
    })
  })

  describe('authenticated branch', () => {
    it('schedules router.push("/") once and passes authInfo to session wrapper', async () => {
      useAuthMock.mockReturnValue({
        isLoading: false,
        authInfo: { token: 'session-token' },
      })

      render(
        <AuthLayout>
          <div>Auth child</div>
        </AuthLayout>
      )

      // Redirect is in useEffect (after commit); assert via waitFor.
      await waitFor(() => {
        expect(mockPush).toHaveBeenCalledTimes(1)
        expect(mockPush).toHaveBeenCalledWith('/')
      })
      expect(screen.queryByTestId('loading-page')).not.toBeInTheDocument()
      expect(screen.getByText('Auth child')).toBeInTheDocument()
      expect(screen.getByTestId('session-wrap')).toHaveAttribute(
        'data-has-session',
        '1'
      )
    })
  })
})
