import React, { Suspense, useEffect, Fragment } from 'react'
import PropTypes from 'prop-types'
import {
  BrowserRouter as Router,
  Switch,
  Route
} from 'react-router-dom'
import _ from 'lodash'
import moment from "moment"
import md5 from "crypto-js/md5"
import querystring from "querystring"

import { BackendTemplate } from "../../../templates"
import { Page404, LoginPage } from "../../../pages"
import { setAccessToken, removeAccessToken } from "./AuthDataSource"
import AuthProvider, { useAuthContext } from "./Auth"

const authenCallbackPath = "/authen-callback"

/**
 * Format url
 */
function trimUrl(url, basePath) {
  return _.trimEnd(basePath, '/') + '/' + _.trimStart(url, '/')
}

/**
 * Login Component 
 */
function LoginComponent({ ...props }) {

  useEffect(() => {
    if (props.location.pathname === authenCallbackPath) {
      const urlParams = new URLSearchParams(props.location.search)
      const authenCode = urlParams.get('code')
      const { clientId, clientSecret, redirectUri } = props

      setAccessToken({ authenCode, clientId, clientSecret, redirectUri })
      props.history.push(props.defaultRoute)
    }
  })

  const _handleLogin = (e) => {
    e.preventDefault();

    const { authenUri, clientId, clientSecret, redirectUri, responseType, stateTimestamp } = props
    const params = {
      client_id: clientId,
      client_secret: clientSecret,
      redirect_uri: redirectUri,
      response_type: responseType
    }
    window.location.href = `${authenUri}?${querystring.stringify(params)}&state=${md5(stateTimestamp)}`
  }

  return (
    <LoginPage
      {...props}
      onClickLogin={_handleLogin}
    />
  )
}

/**
 * Auth Wrapper 
 */
function AuthWrapper({ ...props }) {
  const { authData, onLogin, onLogout } = useAuthContext()
  const loggedIn = authData ? true : false

  function _handleLogin() {
    const urlParams = new URLSearchParams(props.location.search)
    const authenCode = urlParams.get('code')
    const { clientId, clientSecret, redirectUri } = props

    onLogin()
    setAccessToken({ authenCode, clientId, clientSecret, redirectUri })
    props.history.push(props.defaultRoute)
  }

  function _handleLogout() {
    onLogout()
    props.history.push(props.basePath)
  }

  return (
    <Fragment>
      {props.render({
        authData,
        loggedIn,
        onLogin: _handleLogin,
        onLogout: _handleLogout
      })}
    </Fragment>
  )
}

/**
 * Main Component 
 */
function BackendSkeleton({ ...props }) {

  useEffect(() => {
    return () => {
      removeAccessToken()
    }
  })

  const routes = _.filter(props.config, value => {
    return value.title !== true && !value.children
  })

  const routeConfig = props.config.filter(value => {
    return value.children
  }).map(value => {
    return value.children
  }).concat(routes).flat().map(value => {
    return {
      ...value,
      path: trimUrl(value.path, props.basePath),
      component: value.component
    }
  })

  const navConfig = {
    items: _.map(props.config, value => {
      return {
        ...value,
        url: !value.children && trimUrl(value.path, props.basePath),
        children: value.children && value.children.map(child => {
          return {
            ...child,
            url: trimUrl(child.path, props.basePath)
          }
        })
      }
    })
  }

  const loading = () => <div className="animated fadeIn pt-1 text-center">Loading...</div>
  const parentProps = props

  return (
    <Router>
      <Suspense fallback={loading()}>
        <Switch>
          <Route exact name="Login" path={props.loginPath} render={props => <LoginComponent {...props} {...parentProps} />} />
          <Route name="Login Callback" path={authenCallbackPath} render={props => <LoginComponent {...parentProps} {...props} />} />
          <Route name="Backend" path={props.basePath} render={props => {
            return (
            
                        <BackendTemplate
                          routeConfig={routeConfig}
                          navConfig={navConfig}
                          {...parentProps}
                          {...props}
                        />
                   
            )
            /*return (
              <AuthProvider>
                <AuthWrapper {...props}>
                  {
                    (authData, loggedIn, onLogin, onLogout) => {
                      console.log('is logged in = ', loggedIn)
                      return (
                        <BackendTemplate
                          routeConfig={routeConfig}
                          navConfig={navConfig}
                          {...parentProps}
                          {...props}
                        />
                      )
                    }
                  }
                </AuthWrapper>
              </AuthProvider>
            )*/
          }} />
          <Route path="*" component={Page404} />
        </Switch>
      </Suspense>
    </Router>
  )
}
export default BackendSkeleton

const RouteWithLayout = ({ component: Component, layout: Layout, ...rest }) => (
  <Route {...rest} render={props => (
    <Layout>
      <Component />
    </Layout>
  )} />
)

BackendSkeleton.propTypes = {
  basePath: PropTypes.string,
  config: PropTypes.array.isRequired,
  clientId: PropTypes.string.isRequired,
  clientSecret: PropTypes.string.isRequired,
  authenUri: PropTypes.string.isRequired,
  redirectUri: PropTypes.string.isRequired,
  responseType: PropTypes.string.isRequired,
  stateTimestamp: PropTypes.number.isRequired,
  defaultRoute: PropTypes.string.isRequired
}
BackendSkeleton.defaultProps = {
  basePath: '/',
  loginPath: '/',
  authenUri: "https://oauth2.eng.psu.ac.th/authorize",
  redirectUri: window.location.origin + authenCallbackPath,
  responseType: "code",
  stateTimestamp: moment().unix(),
  defaultRoute: "/dashboard"
}