import React, { useCallback, useEffect, useRef, useState } from 'react'
import { CaretRightOutlined } from '@ant-design/icons'
import styles from './index.module.scss'
import SpinLoding from '@/components/SpinLoding'
import { Route, Switch, useLocation } from 'react-router-dom'
import AuthRoute from '@/components/AuthRoute'
import classNames from 'classnames'
import history from '@/utils/history'
import { Button, Form, Input, Modal } from 'antd'
import { Base64 } from 'js-base64'
import encodeStr from '@/utils/pass'
import { API_getRoleArr, passWordEditAPI } from '@/store/action/layout'
import { changSetFu, getTokenInfo, removeTokenInfo } from '@/utils/storage'
import { MessageFu } from '@/utils/message'
import logoImg from '@/assets/img/logo2.png'
import NotFound from '@/components/NotFound'

import { RouterType, RouterTypeRow } from '@/types'
import tabLeftArr, { routerSon } from './data'
import MyPopconfirm from '@/components/MyPopconfirm'
import { TypeZ5Role } from '../Z_system/Z5role/type'
import { useDispatch, useSelector } from 'react-redux'
import { Z1_APIgetDict } from '@/store/action/Z1dict'
import store, { RootState } from '@/store'
import { baseURL } from '@/utils/http'
import baseTouXiangImg from '@/assets/img/user.png'
import { Z5_APIgetInfo } from '@/store/action/Z5role'

function Layout() {
  // 获取角色下载权限
  const getDownRole = useCallback(async () => {
    const info = getTokenInfo().user
    if (info && info.roleId) {
      const res = await Z5_APIgetInfo(info.roleId)
      if (res.code === 0) {
        const data = res.data.role
        store.dispatch({
          type: 'layout/downImg',
          payload: {
            可见: data.scopeGoodsFile === 1 ? '可见' : '不可见',
            图片: data.scopeGoodsFileDownload === 1 ? '原图和缩略图' : '缩略图'
          }
        })
      }
    }
  }, [])

  // 用户信息存到仓库
  useEffect(() => {
    store.dispatch({ type: 'layout/userInfo', payload: (getTokenInfo() || {}).user })
    getDownRole()
  }, [getDownRole])

  // 获取用户信息
  const { userInfo, passEditShow } = useSelector((state: RootState) => state.A0Layout)

  const dispatch = useDispatch()

  // 很多地方会用到的下拉框 或者级联数据
  useEffect(() => {
    // 获取全部级联数据
    dispatch(Z1_APIgetDict())
  }, [dispatch])

  // 当前路径选中的左侧菜单
  const location = useLocation()
  const [path, setPath] = useState('')

  useEffect(() => {
    const arr = location.pathname.split('/')
    let pathTemp = '/'
    if (arr[1]) pathTemp = '/' + arr[1]

    setPath(pathTemp)
  }, [location])

  // 获取用户权限信息
  const getUserAuthFu = useCallback(async () => {
    const userInfo = getTokenInfo().user

    // 获取权限
    const getRoleRes = await API_getRoleArr(userInfo.roleId)

    if (getRoleRes.code === 0) {
      const getRoleArr: TypeZ5Role[] = getRoleRes.data || []

      const isOkIdArr: number[] = [9901]

      getRoleArr.forEach(v1 => {
        if (v1.children) {
          v1.children.forEach(v2 => {
            if (v2.authority) isOkIdArr.push(v2.id)
          })
        }
      })

      // 是管理员
      if (userInfo.isAdmin === 1) {
        // push角色管理
        isOkIdArr.push(9900)
      }

      // 待完善 手动打开一些页面
      ;[9800, 9801, 9802, 9803].forEach(v => {
        isOkIdArr.push(v)
      })

      const tempArr: RouterTypeRow[] = []

      tabLeftArr.forEach(v1 => {
        if (v1.son && v1.son[0]) {
          v1.son.forEach(v2 => {
            if (isOkIdArr.includes(v2.id)) {
              tempArr.push(v2)
            }
          })
        }
      })

      setRouterCom(tempArr)

      // 如果当前页面没有权限了，跳转有权限的第一个页面
      const urlAll = window.location.hash

      const isNowPath = urlAll.replace('#', '')
      const pathArr = tempArr.map(v => v.pathLast || v.path)

      const routerSonArr = routerSon.map(v => v.path)

      const lastArr = [...pathArr, ...routerSonArr]

      let flagPush = true

      lastArr.forEach(v => {
        if (v === '/') {
          if (isNowPath === '/') flagPush = false
        } else {
          if (isNowPath.includes(v)) flagPush = false
        }
      })

      if (flagPush) history.push(pathArr[0])

      const resList = tabLeftArr.map(v => ({
        ...v,
        son: v.son.filter(c => isOkIdArr.includes(c.id))
      }))

      setList(resList)
    }
  }, [])

  useEffect(() => {
    getUserAuthFu()
  }, [getUserAuthFu])

  // 左侧菜单 信息
  const [list, setList] = useState([] as RouterType)

  // 路由信息（过滤之后的）
  const [RouterCom, setRouterCom] = useState<RouterTypeRow[]>([])

  // useEffect(() => {
  //   console.log(123, list);
  // }, [list]);

  // 点击跳转
  const pathCutFu = useCallback((item: RouterTypeRow) => {
    history.push(item.path)
    if (item.name !== '业务中心') changSetFu(item)
  }, [])

  // 拿到新密码的输入框的值
  const oldPasswordValue = useRef('')

  const checkPassWord = (rule: any, value: any = '') => {
    if (value !== oldPasswordValue.current) return Promise.reject('新密码不一致!')
    else return Promise.resolve(value)
  }

  const onFinish = async (values: any) => {
    // 通过校验之后发送请求
    if (values.oldPassword === values.newPassword) return MessageFu.warning('新旧密码不能相同!')

    const regex =
      /^(?=.*[A-Za-z])(?=.*\d)|(?=.*[A-Za-z])(?=.*[!@#$%^&*])|(?=.*\d)(?=.*[!@#$%^&*])[A-Za-z\d!@#$%^&*]{8,}$/

    const flagPass = regex.test(values.newPassword)
    if (!flagPass) {
      return MessageFu.warning('密码要求由数字、字母或特殊字符中2种方式组成')
    }

    const obj = {
      oldPassword: encodeStr(Base64.encode(values.oldPassword)),
      newPassword: encodeStr(Base64.encode(values.newPassword))
    }
    const res: any = await passWordEditAPI(obj)
    if (res.code === 0) {
      MessageFu.success('修改成功!')
      loginExit()
    }
  }

  // 点击退出登录
  const loginExit = () => {
    removeTokenInfo()
    history.push('/login')
  }

  // 点击用户 出来 退出登录 修改密码
  const [isUserBtnShow, setIsUserBtnShow] = useState(false)

  // path的高亮判断
  const pathAcFu = useCallback(
    (url: string) => {
      let flag = false
      if (url === '/') {
        if (path.includes('/_') || path === '/') flag = true
      } else {
        if (path.includes(url)) flag = true
      }
      return flag
    },
    [path]
  )

  return (
    <div className={styles.Layout}>
      {/* 左边 */}
      <div className='layoutLeft'>
        <div className='layoutLeftTop'>
          <img src={logoImg} alt='' />
        </div>
        {/* 左边主体 */}
        <div className='layoutLeftMain mySorrl'>
          {list.map(v => (
            <div className={classNames('layoutLRowBox')} key={v.id} hidden={!v.son.length}>
              {/* 这个项目没有一级目录 */}
              <div className='layoutLRowBoxTxt'>{v.name}</div>
              {v.son.map(v2 => (
                <div
                  key={v2.id}
                  hidden={v2.id >= 9901}
                  className={classNames('layoutLRowBoxRow', pathAcFu(v2.path) ? 'active' : '')}
                  onClick={() => pathCutFu(v2)}
                >
                  {v2.name}
                </div>
              ))}
            </div>
          ))}
        </div>
      </div>
      {/* 右边 */}
      <div className='layoutRight'>
        <div className='layoutRightTop'>
          {/* 用户相关 */}
          <div
            className={classNames('user', isUserBtnShow ? 'userShow' : '')}
            onMouseLeave={() => setIsUserBtnShow(false)}
          >
            <div className='userNameBox' onClick={() => setIsUserBtnShow(true)}>
              <img src={userInfo.thumb ? baseURL + userInfo.thumb : baseTouXiangImg} alt='' />

              {userInfo.realName || userInfo.userName || '匿名'}

              <div className='userInco userInco2'>
                <CaretRightOutlined />
              </div>
            </div>

            <div className='userSet'>
              <div>
                <span
                  onClick={() => store.dispatch({ type: 'layout/passEditShow', payload: true })}
                >
                  修改密码
                </span>
                <MyPopconfirm txtK='退出登录' onConfirm={loginExit} Dom='退出登录' loc='bottom' />
              </div>
            </div>
          </div>
        </div>
        {/* 右边主体 */}
        <div className='layoutRightMain'>
          {/* 二级路由页面 */}
          <div className='mainBoxR'>
            <React.Suspense fallback={<SpinLoding />}>
              <Switch>
                {/* 左侧tab栏页面 */}
                {RouterCom.map(v => (
                  <AuthRoute key={v.id} exact path={v.path} component={v.Com} />
                ))}

                {/* 非tab栏页面 */}
                {routerSon.map(v => (
                  <AuthRoute key={v.id} exact path={v.path} component={v.Com} />
                ))}

                <Route path='*' component={NotFound} />
              </Switch>
            </React.Suspense>
          </div>
        </div>
      </div>

      {/* 点击修改密码打开的对话框 */}
      <Modal
        destroyOnClose
        open={passEditShow}
        title='修改密码'
        onCancel={() => store.dispatch({ type: 'layout/passEditShow', payload: false })}
        footer={
          [] // 设置footer为空，去掉 取消 确定默认按钮
        }
      >
        <Form
          scrollToFirstError={true}
          name='basic'
          labelCol={{ span: 5 }}
          wrapperCol={{ span: 16 }}
          onFinish={onFinish}
          autoComplete='off'
        >
          <Form.Item
            label='旧密码'
            name='oldPassword'
            rules={[{ required: true, message: '不能为空!' }]}
            getValueFromEvent={e => e.target.value.replace(/\s+/g, '')}
          >
            <Input.Password maxLength={20} />
          </Form.Item>

          <Form.Item
            label='新密码'
            name='newPassword'
            rules={[
              { required: true, message: '不能为空!' },
              { min: 6, max: 20, message: '密码长度为6-20个字符!' }
            ]}
            getValueFromEvent={e => e.target.value.replace(/\s+/g, '')}
          >
            <Input.Password
              maxLength={15}
              onChange={e => (oldPasswordValue.current = e.target.value)}
            />
          </Form.Item>

          <Form.Item
            label='确定新密码'
            name='checkPass'
            rules={[{ validator: checkPassWord }]}
            getValueFromEvent={e => e.target.value.replace(/\s+/g, '')}
          >
            <Input.Password maxLength={15} />
          </Form.Item>

          <Form.Item wrapperCol={{ offset: 14, span: 16 }}>
            <Button onClick={() => store.dispatch({ type: 'layout/passEditShow', payload: false })}>
              取消
            </Button>
            &emsp;
            <Button type='primary' htmlType='submit'>
              确定
            </Button>
          </Form.Item>
        </Form>
      </Modal>
    </div>
  )
}

// 使用 React.memo 来优化组件，避免组件的无效更新，类似 类组件里面的PureComponent
const MemoLayout = React.memo(Layout)
export default MemoLayout
