import * as React from 'react'

import Button from '../Button/Button'
import isClient from '../../services/isClient'
import StandardTable from '../TableComponents/StandardTable'
import TextInput from '../Form/TextInput'
import { type ConfigItemType } from '../TableComponents/StandardTable.models'
import styles from './_dev-tools.module.scss'
import { c } from '../../translations/LibraryTranslationService'
import { getEnvironmentName } from '../../services/apiEndpointHelpers'

const { useState, useEffect } = React

const importMapUrl = `https://shared-assets${
  getEnvironmentName() === 'production' ? '' : '-staging'
}.pattern.com/import-map.json`

type ImportMap = {
  imports: Record<string, string>
}
type ImportMapState =
  | {
      state: 'loading'
      data: ImportMap
    }
  | {
      state: 'resolved'
      data: ImportMap
    }
  | {
      state: 'error'
      error: Error
    }

function getLocalStoragePrefix() {
  return isClient
    ? (window as unknown as { frontendLocalStoragePrefix: string })
        .frontendLocalStoragePrefix
    : ''
}

export function FrontendOverrides(): React.JSX.Element {
  const [importMap, setImportMap] = useState<ImportMapState>({
    state: 'loading',
    data: {
      imports: {},
    },
  })

  useEffect(() => {
    const controller = new AbortController()
    const { signal } = controller
    fetch(importMapUrl, { signal })
      .then((response) => response.json())
      .then((data) => {
        setImportMap({ state: 'resolved', data })
      })
      .catch((error) => {
        if (!signal.aborted) {
          setImportMap({ state: 'error', error })
        }
      })

    return () => {
      controller.abort()
    }
  }, [])

  if (importMap.state === 'error')
    return (
      <div>
        {c('errorImportMap', {
          error: importMap.error.message,
        })}
      </div>
    )

  const Table = () => {
    const allImports = importMap.data.imports
    const data = Object.keys(allImports).map((packageName) => ({
      name: packageName,
    }))

    type DataType = { name: string }

    const UrlInput = ({ data }: { data: { name: string } }) => {
      const [url, setUrl] = useState(
        localStorage.getItem(`${getLocalStoragePrefix()}${data.name}`) ??
          allImports[data.name],
      )

      function setNewUrl(newUrl: string) {
        const defaultUrl =
          importMap.state === 'resolved' && allImports[data.name]
        if (newUrl === defaultUrl) {
          // if setting the url to the one that's in the import map, remove the localStorage override
          localStorage.removeItem(`${getLocalStoragePrefix()}${data.name}`)
        } else {
          localStorage.setItem(`${getLocalStoragePrefix()}${data.name}`, newUrl)
        }
        setUrl(newUrl)
      }

      return (
        <div className={styles.inputAndButton}>
          <TextInput
            value={url}
            callout={(_, value) => {
              const fourDigitPortRegex = /^\d{4}$/g
              if (fourDigitPortRegex.test(value.toString())) {
                const packageNameArr = data.name.split('/')
                setNewUrl(
                  `http://localhost:${value}/main.${
                    packageNameArr[packageNameArr.length - 1]
                  }.js`,
                )
              } else {
                setNewUrl(value.toString())
              }
            }}
          />
          <Button
            onClick={() => setNewUrl(allImports[data.name])}
            icon='reload'
            tooltip={{
              tooltipContent: c('tooltipFrontEndOverrideReset'),
            }}
          />
        </div>
      )
    }

    const tableConfig: ConfigItemType<DataType, Record<string, unknown>>[] = [
      {
        label: c('packageName'),
        name: 'name',
        noSort: true,
        cell: {
          children: (data: DataType): React.JSX.Element => {
            return <span>{data.name}</span>
          },
        },
      },
      {
        label: c('url'),
        name: 'url',
        noSort: true,
        cell: {
          children: (data: DataType): React.JSX.Element => {
            return <UrlInput data={data} />
          },
        },
      },
    ]

    return (
      <StandardTable
        data={data}
        config={tableConfig}
        dataKey='name'
        hasData={Object.keys(allImports).length > 0}
        successStatus={importMap.state === 'resolved'}
        loading={importMap.state === 'loading'}
        tableId='front-end-overrides'
        noDataFields={{
          primaryText: c('noDataAvailable'),
        }}
        noMobileView
        customWidth='auto'
        noSort
      />
    )
  }

  return <Table />
}
