/* eslint-disable no-console */
import React from 'react'
import {isPlainObject} from 'lodash'
import PropTypes from 'prop-types'
import sanityClient from 'part:@sanity/base/client'
import AnchorButton from 'part:@sanity/components/buttons/anchor'
import styles from './ProjectInfo.css'

function isUrl(url) {
  return /^https?:\/\//.test(`${url}`)
}

function getGraphQlUrl(projectId) {
  return `https://${projectId}.api.sanity.io/v1/graphql/test`
}

function getGroqUrl(projectId) {
  return `https://${projectId}.api.sanity.io/v1/groq/test`
}

function getManageUrl(projectId) {
  return `https://manage.sanity.io/projects/${projectId}`
}

class ProjectInfo extends React.Component {
  static propTypes = {
    data: PropTypes.array
  }
  static defaultProps = {
    data: []
  }

  state = {
    studioHost: null,
    graphqlApi: null,
    error: null
  }

  componentDidMount() {
    const {projectId} = sanityClient.config()
    // fetch project data
    sanityClient.projects
      .getById(projectId)
      .then(result => {
        const {studioHost} = result
        this.setState({studioHost: studioHost ? `https://${studioHost}.sanity.studio` : null})
      })
      .catch(error => {
        console.log('Error while looking for studioHost', error)
        this.setState({
          studioHost: {
            error: 'Something went wrong while looking up studioHost. See console.'
          }
        })
      })

    // ping assumed graphql endpoint
    sanityClient
      .request({
        method: 'HEAD',
        uri: `/graphql/${sanityClient.config().dataset}/default`
      })
      .then(response => {
        this.setState({graphqlApi: getGraphQlUrl(projectId)})
      })
      .catch(error => {
        if (error.statusCode === 404) {
          this.setState({graphqlApi: null})
        } else {
          console.log('Error while looking for graphqlApi', error)
          this.setState({
            graphqlApi: {
              error: 'Something went wrong while looking up graphqlApi. See console.'
            }
          })
        }
      })
  }

  assembleTableRows() {
    const {projectId, dataset} = sanityClient.config()
    const {graphqlApi, studioHost} = this.state
    const propsData = this.props.data

    let result = [
      {
        title: 'Sanity project',
        rows: [{title: 'Project ID', value: projectId}, {title: 'Dataset', value: dataset}]
      }
    ]

    // Handle any apps
    const apps = [studioHost ? {title: 'Studio', value: studioHost} : null]
      .concat(propsData.filter(item => item.category === 'apps'))
      .filter(Boolean)
    if (apps.length > 0) {
      result = result.concat([{title: 'Apps', rows: apps}])
    }

    // Handle APIs
    result = result.concat(
      [
        {
          title: 'APIs',
          rows: [
            {title: 'GROQ', value: getGroqUrl(projectId)},
            {title: 'GraphQL', value: graphqlApi || 'Not deployed'}
          ]
        }
      ],
      propsData.filter(item => item.category === 'apis')
    )

    // Handle whatever else there might be
    const otherStuff = {}
    propsData.forEach(item => {
      if (item.category !== 'apps' && item.category !== 'apis') {
        if (!otherStuff[item.category]) {
          otherStuff[item.category] = []
        }
        otherStuff[item.category].push(item)
      }
    })

    Object.keys(otherStuff).forEach(category => {
      result.push({title: category})
      result = result.concat(otherStuff[category])
    })

    return result
  }

  render() {
    const {error} = this.state

    if (error) {
      return <pre>{JSON.stringify(error, null, 2)}</pre>
    }

    return (
      <div className={styles.container}>
        <header className={styles.header}>
          <h2 className={styles.title}>Project info</h2>
        </header>
        <table className={styles.table}>
          {this.assembleTableRows().map(item => {
            if (!item || !item.rows) {
              return null
            }

            return (
              <tbody key={item.title}>
                <tr>
                  <th colSpan="2" className={styles.sectionHeader}>
                    {item.title}
                  </th>
                </tr>
                {item.rows.map(row => {
                  return (
                    <tr key={row.title}>
                      <th>{row.title}</th>
                      {isPlainObject(row.value) && (
                        <td className={styles.apiError}>{row.value.error}</td>
                      )}
                      {!isPlainObject(row.value) && (
                        <td>
                          {isUrl(row.value) ? <a href={row.value}>{row.value}</a> : row.value}
                        </td>
                      )}
                    </tr>
                  )
                })}
              </tbody>
            )
          })}
        </table>
        <div className={styles.buttonContainer}>
          <AnchorButton
            href={getManageUrl(sanityClient.clientConfig.projectId)}
            bleed
            color="primary"
            kind="simple"
          >
            Manage project
          </AnchorButton>
        </div>
      </div>
    )
  }
}

export default ProjectInfo

@@ -831,25 +831,8 @@
 Api:
- null,%0A    error:
  nul
@@ -3312,25 +3312,24 @@
    %7D%0A    %7D)%0A
-%0A
     Object.k
@@ -3404,40 +3404,16 @@
 gory
-%7D)%0A      result = result.concat(
+, rows: 
 othe
@@ -3428,16 +3428,17 @@
 ategory%5D
+%7D
 )%0A    %7D)
@@ -3479,121 +3479,8 @@
 ) %7B%0A
-    const %7Berror%7D = this.state%0A%0A    if (error) %7B%0A      return %3Cpre%3E%7BJSON.stringify(error, null, 2)%7D%3C/pre%3E%0A    %7D%0A%0A
     

Fix additional categories render bug in project-info