import useTheme from '../use-theme'
import React, { ReactElement } from 'react'
import { StyleRegistry, createStyleRegistry } from 'styled-jsx'

export type FlushToReact = <T>(opts?: { nonce?: string }) => Array<ReactElement<T>>

const registry = createStyleRegistry()
const flush: FlushToReact = (opts) => registry.styles(opts)

const CssBaseline: React.FC<React.PropsWithChildren<unknown>> = ({ children }) => {
  const theme = useTheme()

  return (
    <StyleRegistry registry={registry}>
      {children}
      <style global jsx>{`
        html,
        body {
          background-color: ${theme.palette.background};
          color: ${theme.palette.foreground};
        }

        html {
          font-size: 16px;
          --hui-icons-background: ${theme.palette.background};
        }

        body {
          -webkit-font-smoothing: antialiased;
          -moz-osx-font-smoothing: grayscale;
          text-rendering: optimizeLegibility;
          font-size: 1rem;
          line-height: 1.5;
          margin: 0;
          padding: 0;
          min-height: 100%;
          position: relative;
          overflow-x: hidden;
          font-family: ${theme.font.sans};
        }

        #__next {
          overflow-x: hidden;
        }

        *,
        *:before,
        *:after {
          box-sizing: border-box;
          text-rendering: geometricPrecision;
          -webkit-tap-highlight-color: transparent;
        }

        p,
        small {
          font-weight: ${theme.font.fontWeights.regular};
          color: inherit;
          letter-spacing: 0.02em;
          font-family: ${theme.font.sans};
        }

        p {
          margin: 0 0 1rem 0;
          font-size: 1em;
          line-height: 1.625em;
        }

        small {
          margin: 0;
          line-height: 1.5;
          font-size: 0.875rem;
        }

        b {
          font-weight: 600;
        }

        span {
          font-size: inherit;
          color: inherit;
          font-weight: inherit;
        }

        img {
          max-width: 100%;
        }

        a {
          cursor: pointer;
          font-size: inherit;
          -webkit-touch-callout: none;
          -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
          -webkit-box-align: center;
          align-items: center;
          color: ${theme.palette.link};
          text-decoration: ${theme.expressiveness.linkStyle};
        }

        a:hover {
          text-decoration: ${theme.expressiveness.linkHoverStyle};
        }

        ul,
        ol {
          padding: 0;
          list-style-type: none;
          margin: ${theme.layout.gapHalf} ${theme.layout.gapHalf} ${theme.layout.gapHalf}
            ${theme.layout.gap};
          color: ${theme.palette.foreground};
        }

        ol {
          list-style-type: decimal;
        }

        li {
          margin-bottom: 0.625rem;
          font-size: 1em;
          line-height: 1.625em;
        }

        h1,
        h2,
        h3,
        h4,
        h5,
        h6 {
          color: inherit;
          margin: 0 0 0.625rem 0;
          letter-spacing: 0.05em;
        }

        h1 {
          font-size: 2rem;
          line-height: 1.295em;
          font-weight: ${theme.font.fontWeights.medium};
        }

        h2 {
          font-size: 1.5rem;
          font-weight: ${theme.font.fontWeights.medium};
        }

        h3 {
          font-size: 1.25rem;
          font-weight: ${theme.font.fontWeights.medium};
        }

        h4 {
          font-size: 1rem;
          font-weight: ${theme.font.fontWeights.medium};
        }

        h5 {
          font-size: 1rem;
          font-weight: ${theme.font.fontWeights.regular};
        }

        h6 {
          font-size: 0.875rem;
          font-weight: ${theme.font.fontWeights.regular};
        }

        button,
        input,
        select,
        textarea {
          font-family: inherit;
          font-size: inherit;
          line-height: inherit;
          color: inherit;
          margin: 0;
        }

        button:focus,
        input:focus,
        select:focus,
        textarea:focus {
          outline: none;
        }

        code {
          color: ${theme.palette.code};
          font-family: ${theme.font.mono};
          font-size: 0.9em;
          white-space: pre-wrap;
        }

        code:before,
        code:after {
          content: '\`';
        }

        pre {
          border: 1px solid ${theme.palette.border};
          border-radius: ${theme.layout.radius};
          padding: calc(${theme.layout.gap} * 0.75) ${theme.layout.gap};
          margin: ${theme.layout.gap} 0;
          font-family: ${theme.font.mono};
          white-space: pre;
          overflow: auto;
          line-height: 1.5;
          text-align: left;
          font-size: 0.875rem;
          -webkit-overflow-scrolling: touch;
        }

        pre code {
          color: ${theme.palette.foreground};
          font-size: 0.8125rem;
          line-height: 1.25rem;
          white-space: pre;
        }

        pre code:before,
        pre code:after {
          display: none;
        }

        pre :global(p) {
          margin: 0;
        }

        pre::-webkit-scrollbar {
          display: none;
          width: 0;
          height: 0;
          background: transparent;
        }

        hr {
          border-color: ${theme.palette.accents_5};
        }

        details {
          background-color: ${theme.palette.border};
          border: none;
        }

        details:focus,
        details:hover,
        details:active {
          outline: none;
        }

        summary {
          cursor: pointer;
          user-select: none;
          list-style: none;
          outline: none;
        }

        summary::-webkit-details-marker,
        summary::before {
          display: none;
        }

        summary:focus,
        summary:hover,
        summary:active {
          outline: none;
          list-style: none;
        }

        blockquote {
          padding: calc(0.667 * ${theme.layout.gap}) ${theme.layout.gap};
          color: ${theme.palette.accents_10};
          background-color: ${theme.palette.accents_1};
          border-radius: ${theme.layout.radius};
          margin: 1.5rem 0;
          border: 1px solid ${theme.palette.border};
        }

        blockquote :global(*:first-child) {
          margin-top: 0;
        }

        blockquote :global(*:last-child) {
          margin-bottom: 0;
        }

        ::selection {
          background-color: ${theme.palette.selection};
          color: ${theme.palette.foreground};
        }
      `}</style>
    </StyleRegistry>
  )
}

type MemoCssBaselineComponent<P = object> = React.NamedExoticComponent<P> & {
  flush: FlushToReact
}

const MemoCssBaseline = React.memo(CssBaseline) as MemoCssBaselineComponent<
  React.PropsWithChildren<unknown>
>
MemoCssBaseline.flush = flush

export default MemoCssBaseline
