import * as React from 'react'
import * as ReactDOM from 'react-dom'

import Button from '../Button/Button'
import FormFooter from '../Form/FormFooter'
import { SideDrawer } from '../SideDrawer/SideDrawer'
import Tabs from '../Tabs/Tabs/Tabs'
import Tag from '../Tag/Tag'
import {
  getApiUrlPrefix,
  getEnvironmentName,
} from '../../services/apiEndpointHelpers'
import { FrontendOverrides } from './FrontendOverrides'
import styles from './_dev-tools.module.scss'
import ToggleTable from './ToggleTable'
import { ToggleProviderContext } from '../ToggleProvider/ToggleProvider'
import { c } from '../../translations/LibraryTranslationService'

const { useState, useEffect } = React
const { createPortal } = ReactDOM

type CalloutType = React.Dispatch<React.SetStateAction<Record<string, unknown>>>
type DevToolsProps = {
  backendNames: string[]
  rerenderCallout: CalloutType
}
export function DevTools({
  backendNames = [],
  rerenderCallout,
}: DevToolsProps): React.JSX.Element | null {
  const [showDevtools, setShowDevtools] = useState(false)
  const [showPanel, setShowPanel] = useState(false)
  const [activeTab, setActiveTab] = useState(0)
  const [activeSubTab, setActiveSubTab] = useState(0)
  const [searchTerm, setSearchTerm] = useState('')
  const { toggles } = React.useContext(ToggleProviderContext)
  const isClient = typeof window !== 'undefined'

  useEffect(() => {
    setShowDevtools(localStorage.getItem('pattern-devtools') === 'true')
  }, [])

  const formattedToggleData = (toggles || [])
    .filter((toggle) => {
      if (searchTerm) {
        return toggle.key.includes(searchTerm)
      }
      return true
    })
    ?.sort((a, b) => {
      // sort alphabetically
      const upperA = a.key.toUpperCase()
      const upperB = b.key.toUpperCase()
      if (upperA < upperB) return -1
      if (upperA > upperB) return 1
      return 0
    })

  if (!showDevtools) return null
  return (
    <>
      {isClient
        ? createPortal(
            <Button
              as='unstyled'
              onClick={() => setShowPanel((prev) => !prev)}
              className={styles.button}
            >
              <Tag color='dark-gray'>{c('patternDevTools')}</Tag>
            </Button>,
            document.body,
          )
        : null}
      <SideDrawer
        isOpen={showPanel}
        closeCallout={() => setShowPanel((prev) => !prev)}
        size='lg'
        headerContent={c('patternDevTools')}
        {...(activeTab === 1
          ? {
              footerContent: ({ close }) => (
                <FormFooter
                  cancelButtonProps={{
                    onClick: () => {
                      close()
                    },
                  }}
                  saveButtonProps={{
                    children: 'Reload App',
                    onClick: () => {
                      isClient && window.location.reload()
                    },
                  }}
                />
              ),
            }
          : {})}
      >
        <Tabs
          tabs={[
            { id: 0, tabName: c('featureToggles') },
            { id: 1, tabName: c('overrides') },
          ]}
          customId='developertools-tabs'
          callout={(tabId: number) => setActiveTab(tabId)}
        />

        <div>
          {activeTab === 0 && (
            <ToggleTable
              searchTerm={searchTerm}
              setSearchTerm={setSearchTerm}
              data={formattedToggleData}
              rerenderCallout={rerenderCallout}
            />
          )}

          {activeTab === 1 && (
            <>
              <Tabs
                tabs={[
                  { id: 0, tabName: c('frontEnd') },
                  { id: 1, tabName: c('backend') },
                ]}
                customId='developertools-tabs'
                callout={(tabId: number) => setActiveSubTab(tabId)}
                subtabs
              />
              <>
                {activeSubTab === 0 && <FrontendOverrides />}

                {activeSubTab === 1 && (
                  <table className='data-table'>
                    <thead>
                      <tr>
                        <th className='py-2 pl-2 text-left'>
                          {c('backendName')}
                        </th>
                        <th className='py-2 text-center'>
                          {c('currentEndpoint')}
                        </th>
                        <th className='py-2 text-center'>
                          {c('localSettings')}
                        </th>
                      </tr>
                    </thead>
                    <tbody>
                      {backendNames.map((backend) => (
                        <BackendOverride key={backend} name={backend} />
                      ))}
                    </tbody>
                  </table>
                )}
              </>
            </>
          )}
        </div>
      </SideDrawer>
    </>
  )
}

type BackendOverrideProps = {
  name: string
}
function BackendOverride({ name }: BackendOverrideProps) {
  const [backendOverride, setBackendOverride] = useState(() => {
    const currentUrl = getApiUrlPrefix(name)
    let environment = 'production'
    if (currentUrl.includes('/staging')) environment = 'development|staging'
    if (localStorage.getItem(`localBackendOverride:${name}:env`)) {
      environment =
        localStorage.getItem(`localBackendOverride:${name}:env`) ?? environment
    }
    return {
      environment,
      endpoint: currentUrl,
    }
  })

  useEffect(() => {
    const localStorageKey = `localBackendOverride:${name}`
    if (backendOverride.environment.includes(getEnvironmentName())) {
      localStorage.removeItem(localStorageKey)
      localStorage.removeItem(`${localStorageKey}:env`)
    } else {
      localStorage.setItem(localStorageKey, backendOverride.endpoint)
      localStorage.setItem(
        `${localStorageKey}:env`,
        backendOverride.environment,
      )
    }
  }, [backendOverride.environment, backendOverride.endpoint, name])

  return (
    <tr>
      <td>{name}</td>
      <td className='text-center'>{backendOverride.endpoint}</td>
      <td className='text-center'>
        <div className='inline-block px-4'>
          <div>{c('prod')}</div>
          <input
            type='radio'
            value='prod'
            checked={backendOverride.environment === 'production'}
            onChange={() =>
              setBackendOverride({
                endpoint: `/${name}`,
                environment: 'production',
              })
            }
          />
        </div>
        <div className='inline-block px-4'>
          <div>{c('staging')}</div>
          <input
            type='radio'
            value='staging'
            checked={backendOverride.environment.includes('staging')}
            onChange={() =>
              setBackendOverride({
                endpoint: `/staging-${name}`,
                environment: 'development|staging',
              })
            }
          />
        </div>
        <div className='inline-block px-4'>
          <div>{c('custom')}</div>
          <input
            type='text'
            onFocus={(evt) => {
              evt.target.select()
            }}
            onChange={(evt) => {
              const fourDigitPortRegex = /^\d{4}$/g
              const newEndpoint = fourDigitPortRegex.test(evt.target.value)
                ? `http://localhost:${evt.target.value}`
                : evt.target.value
              setBackendOverride({
                environment: 'custom',
                endpoint: newEndpoint,
              })
            }}
            value={
              backendOverride.environment === 'custom'
                ? backendOverride.endpoint
                : ''
            }
          />
        </div>
      </td>
    </tr>
  )
}
