import { NAVIGATION_CLOSE } from '#amidala/main/shared/icons.js'
import { isPublish } from '#amidala/main/shared/wcm-mode.js'
import CCPA_ICON from './icons/ccpa.svg'
import INFO_ICON from './icons/info.svg'
import { getProviderData, notifyProvider } from './provider-onetrust.js'

const { h, preactHooks, matter, register, setConsent, getConsent } = globalThis.ami
const { Box, Link, Heading, Button, Logo, Popup, Input, Table, RichText, SVG, Icon } = matter
const { useState, useLayoutEffect } = preactHooks

function ConsentBanner ({ src, 'link-text': linkText, 'ccpa-icon': ccpaIcon, 'disable-list': disableList }) {
  if (!src || !linkText) {
    return null
  }

  const consent = getConsent()
  const [state, setState] = useState({ popup: !consent && isPublish ? 'banner' : null, data: null })

  // Load consent data - only if needed.
  useLayoutEffect(() => {
    if (state.popup && !state.data) {
      getProviderData(src, disableList)
        .then(data => setState(prevState => ({ ...prevState, data })))
        .catch(console.error)
    }
  }, [state.popup])

  return [
    // Modify cookie preferences link.
    h(Box,
      h(Link, {
        onClick: () => {
          setState({ ...state, popup: 'settings' })
        },
        _model: { name: linkText, value: '#' },
        _variant: 'simple',
        className: 'text-sm',
        children: h('span', { className: 'flex items-center gap-1' },
          ccpaIcon && h('span',
            h(SVG, { _model: { src: CCPA_ICON } })
          ),
          h('span', linkText)
        )
      })
    ),
    state.data && [
      // Banner.
      h(Popup, { _modal: false, _show: state.popup === 'banner', _layout: 'toast', 'aria-label': state.data.title },
        h(Banner, {
          data: state.data,
          async onAccept () {
            await setConsentAndNotifyProvider({ functional: true, statistics: true, preferences: true, marketing: true })
            setState({ ...state, popup: null })
          },
          async onReject () {
            await setConsentAndNotifyProvider({})
            setState({ ...state, popup: null })
          },
          onSettings () {
            setState({ ...state, popup: 'settings' })
          }

        })
      ),
      // Settings
      h(Popup, { _modal: true, _show: state.popup === 'settings', 'aria-label': state.data.title },
        h(Settings, {
          data: state.data,
          onClose () {
            setState({ ...state, popup: consent ? null : 'banner' })
          },
          async onReject () {
            await setConsentAndNotifyProvider({})
            setState({ ...state, popup: null })
          },
          onCookies () {
            setState({ ...state, popup: 'cookies' })
          },
          async onSave (userConsent) {
            await setConsentAndNotifyProvider(userConsent)
            setState({ ...state, popup: null })
          }
        })
      ),
      // Cookies
      h(Popup, { _modal: true, _show: state.popup === 'cookies', 'aria-label': state.data.title },
        h(Cookies, {
          data: state.data,
          onSettings () {
            setState({ ...state, popup: 'settings' })
          }
        })
      )
    ]
  ]
}

function Banner ({ data, onAccept, onReject, onSettings }) {
  return [
    h(Logo),
    data.banner.title && h(Heading, { _level: 3 }, data.banner.title),
    h(RichText, data.banner.text),
    h('div', { className: 'flex justify-end lg:space-x-5 md:space-x-5 sm:flex-col sm:space-y-5' },
      // Manage cookies.
      h('div', { classList: 'flex justify-center items-center' },
        h(Link, {
          _variant: 'underline',
          _model: { name: data.banner.buttonSettings, value: '#' },
          onClick: event => {
            event.preventDefault()
            onSettings()
          }
        })
      ),
      h('div', { className: 'flex gap-5 justify-end lg:flex-row-reverse md:flex-row-reverse sm:flex-col ' },
        // Accept optional cookies.
        h(Button, {
          _model: { name: data.banner.buttonAccept },
          className: 'sm:w-full',
          onClick: event => {
            event.preventDefault()
            onAccept()
          }
        }),
        // Reject optional cookies.
        data.banner.buttonReject && h(Button, {
          _model: { name: data.banner.buttonReject },
          className: 'sm:w-full',
          onClick: event => {
            event.preventDefault()
            onReject()
          }
        })
      )
    )
  ]
}

function Settings ({ data, onSave, onReject, onCookies, onClose }) {
  const consent = getConsent() ?? {}
  return [
    h(LogoHeading, { closeLabel: data.settings.buttonClose, onClose }),
    navigator.globalPrivacyControl && h('div', { className: 'flex items-center gap-2' },
      h('span', { className: 'grow-0 shrink-0' },
        h(Icon, INFO_ICON)
      ),
      h('p', data.settings.gcpText)
    ),
    data.settings.title && h(Heading, { _level: 3 }, data.settings.title),
    h(RichText, data.settings.text),
    h(Heading, { _level: 3 }, data.settings.categories),
    h('div', { className: 'space-y-4', 'data-form': '' },
      Object.values(data.groups).map(g => h('div',
        h('label', { className: 'space-x-2 inline-flex items-center font-bold cursor-pointer' },
          h(Input, { type: 'checkbox', name: g.name, checked: consent[g.name] ?? g.alwaysActive, value: true, disabled: g.alwaysActive }),
          h('span', g.title)
        ),
        h('p', g.text)
      )),
      h('div', { className: 'flex justify-end lg:space-x-5 md:space-x-5 sm:flex-col sm:space-y-5' },
        // Cookie list.
        data.cookies.length > 0 && h('div', { classList: 'flex justify-center items-center' },
          h(Link, {
            _variant: 'underline',
            _model: { name: data.list.title, value: '#' },
            onClick: event => {
              event.preventDefault()
              onCookies()
            }
          })
        ),
        // Save preferences.
        h(Button, {
          _model: { name: data.settings.buttonConfirm },
          className: 'sm:w-full',
          onClick: event => {
            event.preventDefault()
            const inputs = [...event.currentTarget.closest('[data-form]').querySelectorAll('input')]
            const userConsent = inputs.reduce((obj, input) => {
              obj[input.name] = input.checked
              return obj
            }, {})
            onSave(userConsent)
          }
        }),
        // Reject optional cookies.
        data.banner.buttonReject && h(Button, {
          _model: { name: data.settings.buttonReject },
          className: 'sm:w-full',
          onClick: event => {
            event.preventDefault()
            onReject()
          }
        })
      )
    )
  ]
}

function Cookies ({ data, onSettings }) {
  return data.cookies.length > 0 && [
    h(LogoHeading, { closeLabel: data.banner.buttonSettings, onClose: onSettings }),
    h(Heading, { _level: 3 }, data.list.title),
    h(RichText, data.list.text),
    h(Table,
      // Headers
      h('tr', Object.keys(data.cookies[0]).map(k => h('th', k))),
      data.groups.map(g => [
        // Group section
        h('tr',
          h('td', { className: 'font-bold', colspan: Object.keys(data.cookies[0]).length }, g.title)
        ),
        g.cookies.map(c => h('tr',
          Object.values(c).map(v => h('td', v))
        ))
      ])
    )
  ]
}

function LogoHeading ({ closeLabel, onClose }) {
  return h('div', { className: 'flex gap-2' },
    h('div', { className: 'grow' },
      h(Logo)
    ),
    onClose && h('div', { className: 'shrink' },
      h(Button, {
        _variant: 'plain',
        _textless: true,
        _size: 'sm',
        _model: { name: closeLabel, icon: NAVIGATION_CLOSE },
        onClick: onClose
      })
    )
  )
}

async function setConsentAndNotifyProvider (consent) {
  const hasConsentedBefore = getConsent() !== null
  setConsent(consent)
  await notifyProvider(consent)

  if (hasConsentedBefore) {
    location.reload()
  }
}

register(ConsentBanner, 'consent-banner')
