import crypto from 'crypto'
import Document, { Head, Main, NextScript } from 'next/document'

const cspHashOf = (text) => {
  const hash = crypto.createHash('sha256')
  hash.update(text)
  return `'sha256-${hash.digest('base64')}'`
}

export default class MyDocument extends Document {
  static async getInitialProps (ctx) {
    let options

    const enhanceComponent = Component => (props) => <div><span id='render-page-enhance-component'>RENDERED</span><Component {...props} /></div>
    const enhanceApp = Component => (props) => <div><span id='render-page-enhance-app'>RENDERED</span><Component {...props} /></div>

    if (ctx.query.withEnhancer) {
      options = enhanceComponent
    } else if (ctx.query.withEnhanceComponent || ctx.query.withEnhanceApp) {
      options = {}
      if (ctx.query.withEnhanceComponent) {
        options.enhanceComponent = enhanceComponent
      }
      if (ctx.query.withEnhanceApp) {
        options.enhanceApp = enhanceApp
      }
    }

    const result = ctx.renderPage(options)

    return { ...result, customProperty: 'Hello Document', withCSP: ctx.query.withCSP }
  }

  render () {
    let csp
    switch (this.props.withCSP) {
      case 'hash':
        csp = `default-src 'self'; script-src 'self' ${cspHashOf(NextScript.getInlineScriptSource(this.props))}; style-src 'self' 'unsafe-inline'`
        break
      case 'nonce':
        csp = `default-src 'self'; script-src 'self' 'nonce-test-nonce'; style-src 'self' 'unsafe-inline'`
        break
    }

    return (
      <html>
        <Head nonce='test-nonce'>
          {csp ? <meta httpEquiv='Content-Security-Policy' content={csp} /> : null}
          <style>{`body { margin: 0 } /* custom! */`}</style>
        </Head>
        <body className='custom_class'>
          <p id='custom-property'>{this.props.customProperty}</p>
          <p id='document-hmr'>Hello Document HMR</p>
          <Main />
          <NextScript nonce='test-nonce' />
        </body>
      </html>
    )
  }
}
