import { memo, ReactNode, useCallback, useState } from 'react'
import { useNavigate, useLocation } from 'react-router-dom'
import { Button, Collapse, Drawer, DrawerProps, Form, FormRule, Input, Popconfirm } from 'antd'
import { useForm } from 'antd/lib/form/Form'

import { useUser } from '@asb/context'
import { Grid, GridItem } from '@components/Grid'
import LoaderPortal from '@components/LoaderPortal'
import { invokeWebApiWrapperAsync } from '@components/factory'
import { isURLAvailable, removeUser } from '@utils'
import { AuthService } from '@api'

import '@styles/user_menu.less'

export type UserMenuProps = DrawerProps & {
    isAdmin?: boolean
    additional?: ReactNode
}

type ChangePasswordForm = {
    'new-password': string
}

const newPasswordRules: FormRule[] = [{ required: true, message: 'Пожалуйста, введите новый пароль!' }]

const confirmPasswordRules: FormRule[] = [({ getFieldValue }) => ({ validator(_, value: string) {
    if (value !== getFieldValue('new-password'))
        return Promise.reject('Пароли не совпадают!')
    return Promise.resolve()
}})]

export const UserMenu = memo<UserMenuProps>(({ isAdmin, additional, ...other }) => {
    const [showLoader, setShowLoader] = useState<boolean>(false)

    const [changeLoginForm] = useForm<ChangePasswordForm>()
    const navigate = useNavigate()
    const location = useLocation()
    const user = useUser()

    const navigateTo = useCallback((to: string) => navigate(to, { state: { from: location.pathname }}), [navigate, location.pathname])

    const onChangePasswordOk = useCallback(() => invokeWebApiWrapperAsync(
        async (values: any) => {
            await AuthService.changePassword(user.id ?? -1, `${values['new-password']}`)
            removeUser()
            navigateTo('/login')
        },
        setShowLoader,
        `Не удалось сменить пароль пользователя ${user.login}`,
        { actionName: 'Смена пароля пользователя' },
    ), [navigateTo])

    const logout = useCallback(() => {
        removeUser()
        navigateTo('/login')
    }, [navigateTo])

    return (
        <Drawer
            closable
            placement={'left'}
            className={'user-menu'}
            title={'Профиль пользователя'}
            {...other}
        >
            <div className={'profile-links'}>
                {isAdmin ? (
                    <Button onClick={() => navigateTo('/')}>Вернуться на сайт</Button>
                ) : isURLAvailable('/admin') && (
                    <Button onClick={() => navigateTo('/admin')}>Панель администратора</Button>
                )}
                <Button type={'ghost'} onClick={logout}>Выход</Button>
            </div>
            <Collapse>
                <Collapse.Panel header={'Данные'} key={'summary'}>
                    <Grid>
                        <GridItem row={1} col={1}>Логин:</GridItem>
                        <GridItem row={1} col={2}>{user.login}</GridItem>
                        <GridItem row={2} col={1}>Фамилия:</GridItem>
                        <GridItem row={2} col={2}>{user.surname}</GridItem>
                        <GridItem row={3} col={1}>Имя:</GridItem>
                        <GridItem row={3} col={2}>{user.name}</GridItem>
                        <GridItem row={4} col={1}>Отчество:</GridItem>
                        <GridItem row={4} col={2}>{user.patronymic}</GridItem>
                        <GridItem row={5} col={1}>E-mail:</GridItem>
                        <GridItem row={5} col={2}>{user.email}</GridItem>
                    </Grid>
                </Collapse.Panel>
                <Collapse.Panel header={'Смена пароля'} key={'change-password'}>
                    <LoaderPortal show={showLoader}>
                        <Form name={'change-password'} form={changeLoginForm} autoComplete={'off'} onFinish={onChangePasswordOk}>
                            <Form.Item name={'new-password'} label={'Новый пароль'} rules={newPasswordRules}>
                                <Input.Password placeholder={'Впишите новый пароль'} />
                            </Form.Item>
                            <Form.Item required name={'confirm-password'} rules={confirmPasswordRules} label={'Подтверждение пароля'}>
                                <Input.Password />
                            </Form.Item>
                            <Form.Item>
                                <Popconfirm title={'Вы уверены что хотите сменить пароль?'} onConfirm={changeLoginForm.submit} placement={'topRight'}>
                                    <Button type={'primary'}>Сменить</Button>
                                </Popconfirm>
                            </Form.Item>
                        </Form>
                    </LoaderPortal>
                </Collapse.Panel>
                {additional}
            </Collapse>
        </Drawer>
    )
})
