import formatTime from '#amidala/main/shared/format-time.js'
import LABELS from './labels.js'
import { ARROW_NEXT } from '#amidala/main/shared/icons.js'

const { h, matter, preactHooks } = globalThis.ami
const { Box, Button, Heading, Input, Link, List, Table, Tabs } = matter
const { useEffect, useRef, useState } = preactHooks

const TEXT_CENTER = 'text-center'

function FormInput ({ label, title, ...props }) {
  return h('label',
    h('div', { className: 'block font-bold', title }, label),
    h(Input, {
      type: 'select',
      ...props
    })
  )
}

function AdminUserForm ({ adminTools }) {
  const adminFormRef = useRef(null)
  const [state, setState] = useState({ isInProgress: false, hasSucceeded: false })

  const onSubmit = event => {
    event.preventDefault()

    const form = adminFormRef.current
    const formData = Object.fromEntries(new FormData(form))

    const toggleForm = setDisabled => {
      for (const element of form.elements) {
        element.disabled = setDisabled
      }
    }

    toggleForm(true)
    setState({ isInProgress: true, hasSucceeded: false })

    adminTools.request('user', formData).then(result => {
      setState({ isInProgress: false, hasSucceeded: Boolean(result) })
      toggleForm(false)
      if (result) {
        // Clear email value as it will be typically used only once.
        form.elements['email'].value = ''
      }
    }).catch(error => {
      toggleForm(false)
      console.error(error)
    })
  }

  return [
    h('form', {
      ref: adminFormRef,
      onSubmit
    },
    h('div', { className: 'flex sm:flex-col md:flex-col lg:items-end gap-5' },
      h('div', { className: 'grow min-w-1/3' },
        h(FormInput, {
          label: 'Email',
          name: 'email',
          required: true,
          type: 'email'
        })
      ),
      h('div', { className: 'grow' },
        h(FormInput, {
          label: 'Action',
          name: 'action',
          children: [
            h('option', { value: 'update' }, 'Update'),
            h('option', { value: 'add' }, 'Add/reactivate'),
            h('option', { value: 'remove' }, 'Remove/deactivate')
          ]
        })
      ),
      h('div', { className: 'grow' },
        h(FormInput, {
          label: 'Quota',
          name: 'quota',
          type: 'number',
          min: '0'
        })
      ),
      h('div', { className: 'grow' },
        h(FormInput, {
          label: 'Admin status',
          name: 'isAdmin',
          children: [
            h('option', { value: '' }, '(no change)'),
            h('option', { value: '1' }, 'Yes'),
            h('option', { value: '0' }, 'No')
          ]
        })
      ),
      h('div', { className: 'grow-0' },
        h(Button, {
          type: 'submit',
          _textless: true,
          disabled: state.isInProgress,
          _model: { name: LABELS.GENERATE_BUTTON, icon: ARROW_NEXT }
        })
      )
    )),
    state.hasSucceeded && h('div', { className: TEXT_CENTER }, 'Action completed successfully.')
  ]
}

function AdminData ({ adminTools, endpoint, dataPanelCache, headings, excludeFields, fieldHandler }) {
  const [state, setState] = useState({ isLoading: true, data: dataPanelCache?.current[endpoint] || null })

  useEffect(() => {
    if (state.data) {
      setState(prev => ({ ...prev, isLoading: false }))
      return
    }
    adminTools.request(endpoint)
      .then(data => {
        setState(prev => ({ ...prev, isLoading: false, data }))
        // Cache data if enabled.
        if (dataPanelCache) {
          dataPanelCache.current[endpoint] = data
        }
      })
      .catch(console.error)
  }, []) // Only a single call.

  if (state.isLoading) {
    return h('div', { className: TEXT_CENTER }, LABELS.LOADING)
  }

  return Boolean(state.data) && h(Table, {
    children: [
      h('tr', headings.map((heading, index) =>
        h('th', { key: index }, heading)
      )),
      state.data?.items?.map((item, index) =>
        h('tr', { key: index },
          Object.entries(item).filter(([field]) => !excludeFields?.includes(field)).map(([field, value], cellIndex) =>
            h('td', { key: cellIndex }, fieldHandler(value, field, item))
          )
        )
      )
    ]
  })
}

function AdminReportLink ({ name, value }) {
  return h(Link, {
    className: 'clickable cursor-pointer hover:underline',
    _model: {
      name,
      value
    },
    onClick: e => {
      e.preventDefault()
      // Bypass external disclaimer.
      window.open(value, '_blank', 'noopener')
    }
  })
}

export default function AdminPanel ({ adminTools }) {
  const [state, setState] = useState({ userList: false, models: false })
  const dataPanelCache = useRef({})

  useEffect(() => {
    const onHashChange = () => {
      const tabStateMap = {
        'tab-user-list': 'userList',
        'tab-models': 'models'
      }

      const stateProp = tabStateMap[globalThis.location.hash.substring(1)]
      if (stateProp) {
        setState(prev => ({
          ...prev,
          [stateProp]: true
        }))
      }
    }
    globalThis.addEventListener('hashchange', onHashChange)
    globalThis.location.hash && onHashChange()

    return () => globalThis.removeEventListener('hashchange', onHashChange)
  }, [])

  return h(Box, { className: 'rounded-2xl bg-bga text-txa' },
    h(Heading, { _level: 2, _size: 4 }, 'Administrator panel'),
    h(Tabs, {
      _model: {
        links: [{ name: 'User management' }, { name: 'User list' }, { name: 'Models' }, { name: 'Reports' }]
      },
      children: [
        h('div', { className: 'space-y-5' }, h(AdminUserForm, { adminTools })),
        h('div', {
          children: state.userList &&
            h(AdminData, {
              adminTools,
              endpoint: 'users',
              dataPanelCache,
              headings: ['Email', 'Quota', 'Usage', 'Prompts', 'Admin'],
              excludeFields: ['isInactive'], // Handled by line-through.
              fieldHandler: (value, field, item) => {
                if (['isInactive', 'isAdmin'].includes(field)) {
                  return h('div', { className: TEXT_CENTER }, value ? '+' : '-')
                }

                if (field === 'email' && item['isInactive']) {
                  return h('span', { className: 'line-through' }, value)
                }

                return value
              }
            })
        }),
        h('div', {
          children: state.models &&
            h(AdminData, {
              adminTools,
              endpoint: 'models',
              dataPanelCache,
              headings: ['Name', 'ID', 'Created', 'Modified'],
              fieldHandler: (value, field) => {
                if (['createdDate', 'modifiedDate'].includes(field)) {
                  const date = new Date(value)
                  return date.getTime() ? formatTime(date, true) : '-'
                }

                return value
              }
            })
        }),
        h('div',
          h(List,
            h('li',
              h('div', h(AdminReportLink, { name: 'Quota usage', value: adminTools.getUrl('reports?id=quota-usage') }))
            ),
            h('li',
              h('div', h(AdminReportLink, { name: 'User prompts', value: adminTools.getUrl('reports?id=user-prompts') }))
            )
          )
        )
      ]
    })
  )
}
