import { render, screen, waitFor } from '@testing-library/react'
import { FluidState, FluidType, TimeStep } from 'enums'
import React from 'react'
import { Provider } from 'react-redux'
import * as chartActions from 'store/chart/chart.slice'
import { mockCustomPopup } from 'tests/__mocks__/customPopup.mock'
import {
  mockExpiredElec,
  mockExpiredGas,
} from 'tests/__mocks__/fluidStatusData.mock'
import { mockTestProfile1 } from 'tests/__mocks__/profileType.mock'
import {
  createMockEcolyoStore,
  mockChartState,
  mockGlobalState,
  mockInitialEcolyoState,
  mockModalState,
} from 'tests/__mocks__/store'
import ConsumptionView from './ConsumptionView'

const mockUpdateProfile = jest.fn()
jest.mock('services/profile.service', () => {
  return jest.fn(() => ({
    updateProfile: mockUpdateProfile,
  }))
})

jest.mock('components/Header/CozyBar', () => 'mock-cozybar')
jest.mock('components/Header/Header', () => 'mock-header')
jest.mock('components/DateNavigator/DateNavigator', () => 'mock-dateNavigator')
jest.mock('components/Content/Content', () => 'mock-content')
jest.mock(
  'components/Consumption/FluidButtons/FluidButtons',
  () => 'mock-fluidButtons'
)
jest.mock('components/FluidChart/FluidChart', () => 'mock-fluidchart')
jest.mock(
  'components/Consumption/ConsumptionDetails/ConsumptionDetails',
  () => 'mock-consumptionDetails'
)
jest.mock('components/Connection/Connection', () => 'mock-connection')
jest.mock(
  'components/Konnector/KonnectorViewerCard',
  () => 'mock-konnectorViewerCard'
)
jest.mock(
  'components/Connection/SGEConnect/SgeConnectView',
  () => 'mock-SgeConnectView'
)

const setCurrentTimeStepSpy = jest.spyOn(chartActions, 'setCurrentTimeStep')

const mockFluidStatus = mockInitialEcolyoState.global.fluidStatus
mockFluidStatus[FluidType.ELECTRICITY].status = FluidState.DONE

const mockChartStateShowOffline = { ...mockChartState, showOfflineData: true }

describe('ConsumptionView component', () => {
  beforeEach(() => {
    jest.clearAllMocks()
  })
  it('should be rendered correctly', async () => {
    const store = createMockEcolyoStore({
      chart: {
        ...mockChartState,
        showOfflineData: true,
      },
      global: {
        ...mockGlobalState,
        fluidStatus: mockFluidStatus,
        releaseNotes: mockInitialEcolyoState.global.releaseNotes,
      },
      modal: mockModalState,
    })
    const { container } = render(
      <Provider store={store}>
        <ConsumptionView fluidType={FluidType.ELECTRICITY} />
      </Provider>
    )
    await waitFor(() => null, { container })
    expect(container.getElementsByTagName('mock-cozybar')[0]).toBeTruthy()
    expect(container.getElementsByTagName('mock-header')[0]).toBeTruthy()
    expect(container.getElementsByTagName('mock-dateNavigator')[0]).toBeTruthy()
    expect(container.getElementsByTagName('mock-fluidButtons')[0]).toBeTruthy()
    expect(container.getElementsByTagName('mock-fluidchart')[0]).toBeTruthy()
    expect(
      container.getElementsByTagName('mock-consumptionDetails')[0]
    ).toBeTruthy()
  })

  it('should set CurrentTimeStep to WEEK when fluid != ELECTRICITY and timeStep = HALF_AN_HOUR', async () => {
    const store = createMockEcolyoStore({
      chart: {
        ...mockChartState,
        currentTimeStep: TimeStep.HALF_AN_HOUR,
      },
      global: {
        ...mockGlobalState,
        fluidStatus: mockInitialEcolyoState.global.fluidStatus,
        releaseNotes: mockInitialEcolyoState.global.releaseNotes,
      },
      modal: mockModalState,
    })
    const { container } = render(
      <Provider store={store}>
        <ConsumptionView fluidType={FluidType.GAS} />
      </Provider>
    )
    await waitFor(() => null, { container })
    expect(setCurrentTimeStepSpy).toHaveBeenCalledTimes(1)
    expect(setCurrentTimeStepSpy).toHaveBeenCalledWith(TimeStep.WEEK)
  })

  it('should render konnector list when no fluid is connected', async () => {
    const store = createMockEcolyoStore({
      chart: mockChartStateShowOffline,
      global: {
        ...mockGlobalState,
        fluidStatus: [],
        releaseNotes: mockInitialEcolyoState.global.releaseNotes,
      },
      modal: mockModalState,
    })
    const { container } = render(
      <Provider store={store}>
        <ConsumptionView fluidType={FluidType.MULTIFLUID} />
      </Provider>
    )
    await waitFor(() => null, { container })
    expect(
      container.getElementsByTagName('mock-consumptionDetails')[0]
    ).toBeTruthy()
  })

  it('should render mutlifluid consumption if at least one fluid is connected without konnectorViewerCard', async () => {
    const store = createMockEcolyoStore({
      chart: mockChartStateShowOffline,
      global: {
        ...mockGlobalState,
        fluidStatus: mockFluidStatus,
        releaseNotes: mockInitialEcolyoState.global.releaseNotes,
      },
      modal: mockModalState,
    })
    const { container } = render(
      <Provider store={store}>
        <ConsumptionView fluidType={FluidType.MULTIFLUID} />
      </Provider>
    )
    await waitFor(() => null, { container })
    expect(
      container.getElementsByTagName('mock-consumptionDetails').item(0)
    ).toBeInTheDocument()
    expect(
      container.getElementsByTagName('mock-konnectorViewerCard').item(0)
    ).not.toBeInTheDocument()
  })

  it('should render Electricity when elec is connected with konnectorViewCard', async () => {
    const store = createMockEcolyoStore({
      chart: mockChartStateShowOffline,
      global: {
        ...mockGlobalState,
        fluidStatus: mockFluidStatus,
        releaseNotes: mockInitialEcolyoState.global.releaseNotes,
      },
      modal: mockModalState,
    })
    const { container } = render(
      <Provider store={store}>
        <ConsumptionView fluidType={FluidType.ELECTRICITY} />
      </Provider>
    )
    await waitFor(() => null, { container })
    expect(
      container.getElementsByTagName('mock-consumptionDetails').item(0)
    ).toBeInTheDocument()
    expect(
      container.getElementsByTagName('mock-konnectorViewerCard').item(0)
    ).toBeInTheDocument()
  })

  describe('Partner Issue Modal', () => {
    it('should render partner issue Modal for electricity', async () => {
      const updatedStatus = mockInitialEcolyoState.global.fluidStatus
      updatedStatus[0] = { ...updatedStatus[0], maintenance: true }
      const store = createMockEcolyoStore({
        chart: mockChartStateShowOffline,
        global: {
          ...mockGlobalState,
          fluidStatus: updatedStatus,
          releaseNotes: mockInitialEcolyoState.global.releaseNotes,
        },
        modal: {
          ...mockModalState,
          partnersIssueModal: { enedis: true, grdf: false, egl: false },
        },
      })
      mockUpdateProfile.mockResolvedValue(mockTestProfile1)
      const { container } = render(
        <Provider store={store}>
          <ConsumptionView fluidType={FluidType.ELECTRICITY} />
        </Provider>
      )
      await waitFor(() => null, { container })
      expect(
        screen.getByRole('presentation', {
          name: 'consumption.partner_issue_modal.accessibility_title',
        })
      ).toBeInTheDocument()
    })

    it('should render partner issue Modal for water', async () => {
      const updatedStatus = mockInitialEcolyoState.global.fluidStatus
      updatedStatus[1] = { ...updatedStatus[1], maintenance: true }
      const store = createMockEcolyoStore({
        chart: mockChartStateShowOffline,
        global: {
          ...mockGlobalState,
          fluidStatus: updatedStatus,
          releaseNotes: mockInitialEcolyoState.global.releaseNotes,
        },
        modal: {
          ...mockModalState,
          partnersIssueModal: { enedis: false, grdf: false, egl: true },
        },
      })
      mockUpdateProfile.mockResolvedValue(mockTestProfile1)
      const { container } = render(
        <Provider store={store}>
          <ConsumptionView fluidType={FluidType.WATER} />
        </Provider>
      )
      await waitFor(() => null, { container })
      expect(
        screen.getByRole('presentation', {
          name: 'consumption.partner_issue_modal.accessibility_title',
        })
      ).toBeInTheDocument()
    })
  })
  it('should show expired modal when a GRDF consent is expired', async () => {
    const updatedStatus = mockInitialEcolyoState.global.fluidStatus
    updatedStatus[0] = mockExpiredGas
    const store = createMockEcolyoStore({
      chart: mockChartStateShowOffline,
      global: {
        ...mockGlobalState,
        fluidStatus: updatedStatus,
        releaseNotes: mockInitialEcolyoState.global.releaseNotes,
      },
      modal: mockModalState,
    })
    const { container } = render(
      <Provider store={store}>
        <ConsumptionView fluidType={FluidType.GAS} />
      </Provider>
    )
    await waitFor(() => null, { container })
    expect(screen.getByText('consent_outdated.title.2')).toBeInTheDocument()
  })
  it('should show expired modal when a Enedis consent is expired', async () => {
    const updatedStatus = mockInitialEcolyoState.global.fluidStatus
    updatedStatus[0] = mockExpiredElec
    const store = createMockEcolyoStore({
      chart: mockChartStateShowOffline,
      global: {
        ...mockGlobalState,
        fluidStatus: updatedStatus,
        releaseNotes: mockInitialEcolyoState.global.releaseNotes,
      },
      modal: mockModalState,
    })
    const { container } = render(
      <Provider store={store}>
        <ConsumptionView fluidType={FluidType.ELECTRICITY} />
      </Provider>
    )
    await waitFor(() => null, { container })
    expect(screen.getByText('consent_outdated.title.0')).toBeInTheDocument()
  })
  it('should render customPopup Modal', async () => {
    const store = createMockEcolyoStore({
      chart: mockChartStateShowOffline,
      global: {
        ...mockGlobalState,
        fluidStatus: mockFluidStatus,
        releaseNotes: mockInitialEcolyoState.global.releaseNotes,
      },
      modal: {
        ...mockModalState,
        customPopupModal: mockCustomPopup,
      },
    })
    mockUpdateProfile.mockResolvedValue(mockTestProfile1)
    const { container } = render(
      <Provider store={store}>
        <ConsumptionView fluidType={FluidType.ELECTRICITY} />
      </Provider>
    )
    await waitFor(() => null, { container })
    expect(screen.getByRole('dialog')).toBeInTheDocument()
  })
  it('should render releaseNotesModal if releaseNotes.show is true', async () => {
    const store = createMockEcolyoStore({
      chart: mockChartStateShowOffline,
      global: {
        ...mockGlobalState,
        fluidStatus: mockFluidStatus,
        releaseNotes: {
          show: true,
          notes: [{ description: 'description', title: 'title' }],
        },
      },
      modal: mockModalState,
    })
    mockUpdateProfile.mockResolvedValue(mockTestProfile1)
    const { container } = render(
      <Provider store={store}>
        <ConsumptionView fluidType={FluidType.ELECTRICITY} />
      </Provider>
    )
    await waitFor(() => null, { container })
    expect(screen.getByRole('dialog')).toBeInTheDocument()
  })
})