// Copyright 2018 Red Hat, Inc
// Copyright 2025 Acme Gating, LLC
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License. You may obtain
// a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations
// under the License.

import React from 'react'
import { render, act } from '@testing-library/react'
import { BrowserRouter as Router } from 'react-router-dom'
import { Provider } from 'react-redux'
import { BroadcastChannel, createLeaderElection } from 'broadcast-channel'

import { fetchInfoIfNeeded } from './actions/info'
import configureStore from './store.prod'
import App from './App'
import ZuulAuthProvider from './ZuulAuthProvider'
import * as api from './api'

vi.mock(import('./api'), async (importOriginal) => {
  const mod = await importOriginal()
  return {
    ...mod,
  fetchInfo: vi.fn(),
  fetchTenants: vi.fn(),
  fetchStatus: vi.fn(),
  fetchConfigErrors: vi.fn(() => Promise.resolve({data: []})),
  }
})

it('renders without crashing', async () => {
  const store = configureStore()
  const channel = new BroadcastChannel('zuul')
  const auth_election = createLeaderElection(channel)
  render(
    <Provider store={store}>
      <ZuulAuthProvider channel={channel} election={auth_election}>
        <Router><App /></Router>
      </ZuulAuthProvider>
    </Provider>
  )
  await auth_election.die()
  await channel.close()
})

it('renders multi tenant', async () => {
  const store = configureStore()
  const channel = new BroadcastChannel('zuul')
  const auth_election = createLeaderElection(channel)
  api.fetchInfo.mockImplementation(
    () => Promise.resolve({data: {
      info: {
        capabilities: {
          auth: {
            realms: {},
            default_realm: null,
          },
        },
      }}})
  )
  api.fetchTenants.mockImplementation(
    () => Promise.resolve({data: [{name: 'openstack'}]})
  )

  const application = render(
    <Provider store={store}>
      <ZuulAuthProvider channel={channel} election={auth_election}>
        <Router><App /></Router>
      </ZuulAuthProvider>
    </Provider>
  )

  await act(async () => {
    await store.dispatch(fetchInfoIfNeeded())
  })

  // Link should be tenant scoped
  // TODO: convert to testing-library
  await application.findAllByRole('link')
  // expect(topMenuLinks[0].props.to).toEqual('/')
  // expect(topMenuLinks[1].props.to).toEqual('/components')
  // expect(topMenuLinks[2].props.to).toEqual('/openapi')
  // expect(topMenuLinks[3].props.to).toEqual('/t/openstack/status')
  // expect(topMenuLinks[4].props.to).toEqual('/t/openstack/projects')
  // Location should be /tenants
  expect(location.pathname).toEqual('/tenants')
  // Info should tell multi tenants
  expect(store.getState().info.tenant).toEqual(undefined)
  // Tenants list has been rendered
  // TODO: convert to testing-library
  // expect(application.root.findAllByType(TenantsPage)).not.toEqual(null)
  // Fetch tenants has been called
  expect(api.fetchTenants).toBeCalled()
  await auth_election.die()
  await channel.close()
})

it('renders single tenant', async () => {
  const store = configureStore()
  const channel = new BroadcastChannel('zuul')
  const auth_election = createLeaderElection(channel)
  api.fetchInfo.mockImplementation(
    () => Promise.resolve({data: {
      info: {
        capabilities: {
          auth: {
            realms: {},
            default_realm: null,
          },
        },
        tenant: 'openstack'}
    }})
  )
  api.fetchStatus.mockImplementation(
    () => Promise.resolve({data: {pipelines: []}})
  )

  const application = render(
    <Provider store={store}>
      <ZuulAuthProvider channel={channel} election={auth_election}>
        <Router><App /></Router>
      </ZuulAuthProvider>
    </Provider>
  )

  await act(async () => {
    await store.dispatch(fetchInfoIfNeeded())
  })

  // Link should be white-label scoped
  // TODO: convert to testing-library
  await application.findAllByRole('link')
  // expect(topMenuLinks[0].props.to).toEqual('/status')
  // expect(topMenuLinks[1].props.to).toEqual('/openapi')
  // expect(topMenuLinks[2].props.to.pathname).toEqual('/status')
  // expect(topMenuLinks[3].props.to.pathname).toEqual('/projects')
  // Location should be /status
  expect(location.pathname).toEqual('/status')
  // Info should tell white label tenant openstack
  expect(store.getState().info.tenant).toEqual('openstack')
  // Status page has been rendered
  // TODO: convert to testing-library
  // expect(application.root.findAllByType(StatusPage)).not.toEqual(null)
  // Fetch status has been called
  expect(api.fetchStatus).toBeCalled()
  await auth_election.die()
  await channel.close()
})
