// @vitest-environment happy-dom
import { afterEach, describe, expect, it, vi } from 'vitest'
import { cleanup, render, screen, waitFor } from '@testing-library/react'

/**
 * Split-login mode (user request: login at a non-obvious path like
 * /securelogin, admin app at /admin). Pins:
 * - `LoginRoot` serves login / setup wizard / forgot-password on its own
 *   mount and hands off to the admin app once a session exists.
 * - `<AdminRoot loginPath>` renders a 404 lookalike for signed-out visitors
 *   instead of a login form, so /admin doesn't advertise the CMS.
 */

vi.mock('../../lib/api.js', () => ({
  cmsApi: vi.fn(async () => ({ data: undefined })),
  ensureCsrfToken: vi.fn(async () => undefined),
  setApiBase: vi.fn(),
}))

// This happy-dom environment doesn't expose a functional localStorage, which
// ThemeProvider/LocaleProvider read on mount.
const storage = new Map<string, string>()
vi.stubGlobal('localStorage', {
  getItem: (k: string) => storage.get(k) ?? null,
  setItem: (k: string, v: string) => void storage.set(k, String(v)),
  removeItem: (k: string) => void storage.delete(k),
  clear: () => storage.clear(),
})

const { LoginRoot } = await import('../../LoginRoot.js')
const { AdminRoot } = await import('../../AdminRoot.js')

afterEach(() => {
  cleanup()
  window.history.replaceState({}, '', '/')
})

const noopLogin = vi.fn(async () => ({ success: true }))

describe('LoginRoot', () => {
  it('renders the login screen for signed-out visitors', () => {
    window.history.replaceState({}, '', '/securelogin')
    render(<LoginRoot config={{}} session={null} onLogin={noopLogin} />)
    expect(screen.getByText('Sign in to your account')).toBeTruthy()
  })

  it('renders the setup wizard while setup is required (first-time install)', () => {
    window.history.replaceState({}, '', '/securelogin/setup')
    render(
      <LoginRoot
        config={{ admin: { branding: { name: 'Acme' } } }}
        session={null}
        setupRequired
        onSetupComplete={vi.fn(async () => ({ success: true }))}
        onLogin={noopLogin}
      />,
    )
    expect(screen.getByText('Welcome to Acme')).toBeTruthy()
  })

  it('serves the forgot-password flow under its own mount', () => {
    window.history.replaceState({}, '', '/securelogin/forgot-password')
    render(<LoginRoot config={{}} session={null} onLogin={noopLogin} />)
    expect(screen.getByText('Reset Password')).toBeTruthy()
  })

  it('hands an authenticated visitor off to the admin app', async () => {
    window.history.replaceState({}, '', '/securelogin')
    const onAuthenticated = vi.fn()
    render(
      <LoginRoot
        config={{}}
        session={{ user: { id: 'u1' } }}
        adminPath="/admin"
        onLogin={noopLogin}
        onAuthenticated={onAuthenticated}
      />,
    )
    expect(screen.getByRole('status').textContent).toContain('Signed in')
    await waitFor(() => expect(onAuthenticated).toHaveBeenCalledWith('/admin'))
    // No login form is offered to an already-authenticated visitor.
    expect(screen.queryByText('Sign in to your account')).toBeNull()
  })
})

describe('AdminRoot with loginPath (hidden login)', () => {
  it('shows a 404 lookalike instead of a login form when signed out', () => {
    window.history.replaceState({}, '', '/admin')
    render(<AdminRoot config={{}} session={null} loginPath="/securelogin" onLogin={noopLogin} />)
    expect(screen.getByText('This page could not be found.')).toBeTruthy()
    expect(screen.queryByText('Sign in to your account')).toBeNull()
  })

  it('hides the setup wizard at the admin mount too (it lives on the login mount)', () => {
    window.history.replaceState({}, '', '/admin')
    render(
      <AdminRoot
        config={{}}
        session={null}
        loginPath="/securelogin"
        setupRequired
        onSetupComplete={vi.fn(async () => ({ success: true }))}
        onLogin={noopLogin}
      />,
    )
    expect(screen.getByText('This page could not be found.')).toBeTruthy()
    expect(screen.queryByText(/Welcome to/)).toBeNull()
  })

  it('keeps the classic inline login when loginPath is not set', () => {
    window.history.replaceState({}, '', '/admin')
    render(<AdminRoot config={{}} session={null} onLogin={noopLogin} />)
    expect(screen.getByText('Sign in to your account')).toBeTruthy()
  })
})
