import { render, waitFor } from '@testing-library/react'
import { createMemoryHistory } from 'history'
import { Router } from 'react-router-dom'

import Callback from './Callback'

const handleAuthenticationMock = jest.fn()
const getLastPasswordResetTimeMock = jest.fn()

jest.mock('@tidbcloud/uikit', () => ({
  Button: ({ children, onClick }: { children?: any; onClick?: () => void }) => (
    <button onClick={onClick}>{children}</button>
  ),
  Flex: ({ children }: { children?: any }) => <div>{children}</div>,
  Group: ({ children }: { children?: any }) => <div>{children}</div>,
  Modal: ({ children, opened }: { children?: any; opened?: boolean }) => (opened ? <div>{children}</div> : null),
  Typography: ({ children }: { children?: any }) => <div>{children}</div>
}))

jest.mock('dbaas/components/Error', () => ({
  ContactMessage: () => null,
  ErrorPanel: ({ message, children }: { message?: string; children?: any }) => (
    <div>
      <div>{message}</div>
      {children}
    </div>
  ),
  ErrorSupportLink: () => null
}))

jest.mock('dbaas/components/Placeholder/index', () => ({
  __esModule: true,
  default: () => <div>loading</div>
}))

jest.mock(
  'common/log',
  () => ({
    log: {
      auth: {
        error: jest.fn(),
        exception: jest.fn(),
        warning: jest.fn()
      },
      error: jest.fn(),
      warning: jest.fn()
    }
  }),
  { virtual: true }
)

jest.mock('../../../config', () => ({
  __esModule: true,
  default: {
    UNION_LAKE_REDIRECT_ORIGINS: ['https://lake.tidbcloud.com']
  }
}))

jest.mock('dbaas/services/auth', () => ({
  __esModule: true,
  default: {
    handleAuthentication: (...args: unknown[]) => handleAuthenticationMock(...args),
    getLastPasswordResetTime: (...args: unknown[]) => getLastPasswordResetTimeMock(...args),
    logout: jest.fn()
  }
}))

jest.mock('dbaas/services', () => ({
  __esModule: true,
  acceptInvitation: jest.fn()
}))

jest.mock('dbaas/services/account', () => ({
  __esModule: true,
  getUserLastVisitHistory: jest.fn()
}))

jest.mock('dbaas/utils/useSessionStorage', () => ({
  __esModule: true,
  default: () => [null, jest.fn(), jest.fn()]
}))

jest.mock('dbaas/utils/tracking', () => ({
  eventTracking: jest.fn(),
  MixpanelEvents: {
    TidbCloudLake: {
      View: {
        EnterClicked: 'TidbCloudLake_View_EnterClicked'
      }
    }
  }
}))

describe('Auth Callback', () => {
  beforeEach(() => {
    handleAuthenticationMock.mockReset()
    getLastPasswordResetTimeMock.mockReset()
    getLastPasswordResetTimeMock.mockResolvedValue(null)
  })

  test('redirects to Lake for valid union login callbacks', async () => {
    const history = createMemoryHistory({
      initialEntries: ['/auth_redirect?returnTo=lake&redirectUri=https%3A%2F%2Flake.tidbcloud.com%2Fwelcome']
    })
    window.history.pushState(
      {},
      '',
      '/auth_redirect?returnTo=lake&redirectUri=https%3A%2F%2Flake.tidbcloud.com%2Fwelcome'
    )

    const replaceMock = jest.fn()
    const originalLocation = window.location
    Object.defineProperty(window, 'location', {
      configurable: true,
      value: {
        ...window.location,
        replace: replaceMock
      }
    })

    handleAuthenticationMock.mockImplementation((onSuccess: () => void) => {
      void onSuccess()
    })

    render(
      <Router history={history}>
        <Callback />
      </Router>
    )

    await waitFor(() => {
      expect(replaceMock).toHaveBeenCalledWith('https://lake.tidbcloud.com/welcome')
    })

    Object.defineProperty(window, 'location', {
      configurable: true,
      value: originalLocation
    })
  })

  test('keeps the existing redirect behavior for non-union callbacks', async () => {
    const history = createMemoryHistory({
      initialEntries: ['/auth_redirect']
    })
    window.history.pushState({}, '', '/auth_redirect')

    const replaceMock = jest.fn()
    const originalLocation = window.location
    Object.defineProperty(window, 'location', {
      configurable: true,
      value: {
        ...window.location,
        replace: replaceMock
      }
    })

    handleAuthenticationMock.mockImplementation((onSuccess: () => void) => {
      void onSuccess()
    })

    render(
      <Router history={history}>
        <Callback />
      </Router>
    )

    await waitFor(() => {
      expect(history.location.pathname).toBe('/')
    })

    expect(replaceMock).not.toHaveBeenCalled()
    Object.defineProperty(window, 'location', {
      configurable: true,
      value: originalLocation
    })
  })
})
